Fragment对fragmentPagerAdapter的引用为null

时间:2015-07-31 06:55:56

标签: android android-fragments callback android-viewpager android-lifecycle

所以我在ViewPager中有5(6?)个片段,它们都通过Activity使用回调相互交互以获取彼此之间的信息。我遇到了一些问题,因为它们需要以特定的顺序启动,有些似乎在其他人准备就绪之前就已经开始了,不管我做了什么,所以我实现了对所有片段的回调,只有在所有片段都是准备就绪:

@Override
public void notifyReady() {
    boolean settingsReady = false;
    boolean fileReady = false;
    boolean recordTableReady = false;
    boolean chartReady = false;
    boolean pieChartReady = false;

    if (settingsFragment != null)
        settingsReady = settingsFragment.isReady();

    if (fileFragment != null)
        fileReady = fileFragment.isReady();

    if (recordTableFragment != null)
        recordTableReady = recordTableFragment.isReady();

    if (chartFragment != null)
        chartReady = chartFragment.isReady();

    if (pieChartFragment != null)
        pieChartReady = pieChartFragment.isReady();

    boolean allReady = settingsReady & fileReady & recordTableReady & chartReady & pieChartReady;

    if (allReady) {
        settingsFragment.initialize();
        fileFragment.initialize();
        recordTableFragment.initialize();
        chartFragment.initialize();
        pieChartFragment.initialize();
    }

我把接口实现放在我的FragmentPagerAdapter中,因为我在那里阅读我应该初始化片段:

@Override
public Fragment getItem(int pos) {
  switch(pos) {
    case 0:
      return new SettingsFragment();
    case 1:
      return new FileFragment();
    case 2:
      return new OracleFragment();  // No implementation yet
    case 3:
      return new RecordTableFragment();
    case 4:
      return new ChartFragment();
    case 5:
      return new PieChartFragment();
    default:
      return null; // BAD
  }
}

除了将回调接口初始化为FragmentPagerAdapter之外:

@Override
public Object instantiateItem(ViewGroup container, int position) {
  Fragment createdFragment = (Fragment) super.instantiateItem(container, position);

  switch (position) {
    case 0:
      settingsFragment = (SettingsFragment) createdFragment;
      settingsFragment.setNotificationListener(this);
      break;
    case 1:
      fileFragment = (FileFragment) createdFragment;
      fileFragment.setNotificationListener(this);
      break;
    case 2:
      oracleFragment = (OracleFragment) createdFragment;
      //oracleFragment.setNotificationListener(this); (This fragment has no implementation yet)
      break;
    case 3:
      recordTableFragment = (RecordTableFragment) createdFragment;
      recordTableFragment.setNotificationListener(this);
      break;
    case 4:
      chartFragment = (ChartFragment) createdFragment;
      chartFragment.setNotificationListener(this);
      break;
    case 5:
      pieChartFragment = (PieChartFragment) createdFragment;
      pieChartFragment.setNotificationListener(this);
      break;
  }
  return createdFragment;
}

我的片段叫了:

public void setNotificationListener(FragmentNotifier fragmentNotifier) {
    this.fragmentNotifier = fragmentNotifier;
}

表示FragmentPagerAdapter将自己设置为接口对象,

@Override
public void onStart() {
    super.onStart();

    ready = true;
    fragmentNotifier.notifyReady();
}

用于初始化。这开始工作得非常好,但是片段注释器在一段时间后返回活动后变为null,并且当活动再次启动时调用片段'onStart(),产生NullPointerException。它为什么变成空?其他字段,比如Fragment对Activity的引用和它提供的接口在执行的这一点上都不为空,我已经用调试器检查了,但是fragmentNotifier IS!为什么呢?!

1 个答案:

答案 0 :(得分:0)

我不会调试你的代码并找出它出错的地方,但我会给你一个更好的解决方案。

我过去经历过这一点,并且我意识到在您的Activity中定义回调的最佳方法是在Fragments中。因此,不要使用setter,而是在Fragments中使用它:

@Override
public void onAttach(Activity activity){

    if (activity instanceof FragmentNotifier)
        mFragmentNotifier  = (FragmentNotifier) activity;
    else throw new IllegalAccessException("Activity must implement the FragmentNotifier interface");

}

这将确保您可以参考您的活动。并添加此项以避免泄露引用:

@Override
public void onDetach(){
    mFragmentNotifier = null;
}