-->

Pass String between two fragments without using an

2019-08-06 09:00发布

问题:

I need to pass the string curDate between NewDateFragment and NewEventFrament, i see many peoples using Bundle, but using these i still having NullPointerException.

I transform the CalendarView to one string named curDate.

public class NewDateFragment extends Fragment {

public String curDate;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_newdate,
            container, false);


    CalendarView calendar = (CalendarView) view.findViewById(R.id.calendarView);

    //sets the listener to be notified upon selected date change.
    calendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
        @Override
        public void onSelectedDayChange(CalendarView view, int year, int month, int day) {
            curDate = day + "/" + month + "/" + year;

            NewDateFragment fragment = new NewDateFragment();
            Bundle bundle = new Bundle();
            bundle.putString("date", curDate);
            fragment.setArguments(bundle);

            Log.d("Current Date:", curDate);
        }
    });

}

public class NewEventFragment extends Fragment {

     // relative code inside onCreateView
     Bundle b = getActivity().getIntent().getExtras();
        final String dDate = b.getString("date");
}

My Logcat:

10-08 18:34:49.036 10293-10293/com.org.feedme.cisvmeeting.activities W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41640d88) 10-08 18:34:49.056 10293-10293/com.org.feedme.cisvmeeting.activities E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.org.feedme.cisvmeeting.activities, PID: 10293 java.lang.NullPointerException at com.org.feedme.fragments.NewEventFragment.attemptCreate(NewEventFragment.java:116) at com.org.feedme.fragments.NewEventFragment$1.onClick(NewEventFragment.java:61) at android.view.View.performClick(View.java:4569) at android.view.View$PerformClick.run(View.java:18570) at android.os.Handler.handleCallback(Handler.java:743) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5212) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method)

Thanks for all the help!

回答1:

An alternative to the given answer would be to use Events. If you really want to avoid coupling your code - meaning getting rid of unnecessary dependence between classes, having a variable inside your Activity is not a good idea. Here is my suggestion:

  • Add EventBus library to your Gradle file:

     compile 'de.greenrobot:eventbus:2.4.0'
    
  • Create a simple plain old java class to represent your event:

    public class CalendarDateSelectedEvent{
       private String currentDate;
    
       public CalendarDateSelectedEvent(String date){
    
          this.currentDate = date;
       }
    
       public String getCurrentDate(){
    
          return currentDate;
       }
    }
    
  • Inside your first fragment where a date is picked, you can post an event to your second fragment as soon as the date is selected like this:

    //somewhere when  a date is selected
    onSelectedDayChanged(String dateSelected){
       EventBus.getDefault().post(new CalendarDateSelectedEvent(dateSelected));
    }
    
  • Finally, inside your second fragment, do the following:

    //could be inside onCreate(Bundle savedInstanceState) method
    @Override
    public void onCreate(Bundle saveInstanceState){
       //......
       EventBus.getDefault().register(this);
    }
    
    @Override
    public void onDestroy(){
       super.onDestroy();
       EventBus.getDefault().unregister(this);
    }
    
    //very important piece here to complete the job
    public void onEvent(CalenderDateSelectedEvent event){
    
        String currentDate = event.getCurrentDate();
        //you can now set this date to view.
    }
    

At this point, you might be asking, why all the hussle to have all these code; but the answer is simple: the activity doesn't have to really know what is happening in either fragments. You have eliminated unnecessary coupling in your code.

If you ever change the activity to do something else, you won't have to change the fragment code.

I hope this helps you see the difference between the two approaches to communicating between fragments!

The first approach (the answer you accepted, involves 3 parties while the second approach involves only 2 parties). It is up to you to choose.

Enjoy!



回答2:

If they're fragments in the same activity, you could very easily access data between them using the activity.

Step 1: Declare a String curDate in your Activity:

public String curDate; //you could also make it private and add a public getter & setter

Step 2: In your NewDateFragment, inside the onSelectedDayChange(), set the activity's curDate to the current date you just calculated:

getActivity().curDate = curDate;

Step 3: In your NewEventFragment, simply get the value from the activity:

public String curDate = getActivity().curDate;