【问题标题】:Pass String between two fragments without using an activity在不使用活动的情况下在两个片段之间传递字符串
【发布时间】:2015-10-09 06:27:59
【问题描述】:

我需要在 NewDateFragment 和 NewEventFrament 之间传递字符串 curDate,我看到很多人使用 Bundle,但使用这些我仍然有 NullPointerException。

我将 CalendarView 转换为一个名为 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");
}

我的日志猫:

10-08 18:34:49.036 10293-10293/com.org.feedme.cisvmeeting.activities W/dalvikvm: threadid=1: 线程退出未捕获异常 (group=0x41640d88) 10-08 18:34:49.056 10293-10293/com.org.feedme.cisvmeeting.activities E/AndroidRuntime: 致命例外:主要 进程:com.org.feedme.cisvmeeting.activities,PID:10293 java.lang.NullPointerException 在 com.org.feedme.fragments.NewEventFragment.attemptCreate(NewEventFragment.java:116) 在 com.org.feedme.fragments.NewEventFragment$1.onClick(NewEventFragment.java:61) 在 android.view.View.performClick(View.java:4569) 在 android.view.View$PerformClick.run(View.java:18570) 在 android.os.Handler.handleCallback(Handler.java:743) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:136) 在 android.app.ActivityThread.main(ActivityThread.java:5212) 在 java.lang.reflect.Method.invokeNative(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:515) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 在 dalvik.system.NativeStart.main(Native Method)

感谢大家的帮助!

【问题讨论】:

  • 您不想将活动用作中间人的确切原因是什么?如果这两个片段紧密相关,那么它们很可能是同一活动的片段,并且应该是。
  • 在我的研究中,使用活动似乎很难,我该怎么做?
  • 您实际上在哪里使用 FragmentManager 加载 onSelectedDayChange 中实例化的 Fragment?

标签: android android-fragments android-studio nullpointerexception android-bundle


【解决方案1】:

给定答案的替代方法是使用事件。如果你真的想避免耦合你的代码——意味着摆脱类之间不必要的依赖,在你的 Activity 中拥有一个变量不是一个好主意。这是我的建议:

  • 将 EventBus 库添加到您的 Gradle 文件中:

     compile 'de.greenrobot:eventbus:2.4.0'
    
  • 创建一个简单的普通 java 类来表示您的事件:

    public class CalendarDateSelectedEvent{
       private String currentDate;
    
       public CalendarDateSelectedEvent(String date){
    
          this.currentDate = date;
       }
    
       public String getCurrentDate(){
    
          return currentDate;
       }
    }
    
  • 在您选择日期的第一个片段中,您可以在选择日期后立即将事件发布到您的第二个片段,如下所示:

    //somewhere when  a date is selected
    onSelectedDayChanged(String dateSelected){
       EventBus.getDefault().post(new CalendarDateSelectedEvent(dateSelected));
    }
    
  • 最后,在您的第二个片段中,执行以下操作:

    //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.
    }
    

此时,您可能会问,为什么要这么麻烦地拥有所有这些代码?但答案很简单:活动不必真正知道任一片段中发生了什么。您已经消除了代码中不必要的耦合。

如果您曾经更改活动以执行其他操作,则无需更改片段代码。

我希望这可以帮助您了解片段之间通信的两种方法之间的区别!

第一种方法(您接受的答案涉及 3 方,而第二种方法仅涉及 2 方)。由您来选择。

享受吧!

【讨论】:

    【解决方案2】:

    如果它们是同一活动中的片段,您可以使用活动非常轻松地访问它们之间的数据。

    第 1 步:在您的 Activity 中声明一个字符串 curDate:

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

    第 2 步:在您的 NewDateFragment 中,在 onSelectedDayChange() 中,将活动的 curDate 设置为您刚刚计算的当前日期:

    getActivity().curDate = curDate;
    

    第 3 步:在您的 NewEventFragment 中,只需从活动中获取值:

    public String curDate = getActivity().curDate;
    

    【讨论】:

    • 为了正确性/可重用性,您应该使用用于在活动和片段之间进行通信的方法创建 am 接口。它们在任何地方都使用接口,并且不会在片段中显式引用特定的 Activity 类。
    猜你喜欢
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    相关资源
    最近更新 更多