Exo*_*Kid 2 android android-fragments
当我启动应用程序时一切正常,但是当我旋转到横向时它崩溃了,因为在Fragment那里有一个字段是NULL.
我不使用setRetainInstance(true)或添加 FragmentsFragmentManager在应用程序启动和应用程序旋转时创建新的 Fragments。
在Activity OnCreate()我创建Fragment并将它们添加到viewPager这样的。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ParentBasicInfoFragment parentBasicInfoFragment = new ParentBasicInfoFragment();
ParentUTCFragment parentUTCFragment = new ParentUTCFragment();
ParentEventsFragment parentEventsFragment = new ParentEventsFragment();
this.mFragments = new ArrayList<>();
this.mFragments.add(parentBasicInfoFragment);
this.mFragments.add(parentUTCFragment);
this.mFragments.add(parentEventsFragment);
this.viewpage.setOffscreenPageLimit(3);
setCurrentTab(0);
this.viewpage.setAdapter(new MainActivityPagerAdapter(getSupportFragmentManager(), this.mFragments));
}
Run Code Online (Sandbox Code Playgroud)
然后我在应用程序上有一个测试按钮,当我按下它时会像
public void test(View view) {
((BaseFragment) MainActivity.this.mFragments.get(MainActivity.this.viewpage.
getCurrentItem())).activityNotifiDataChange("hello");
}
Run Code Online (Sandbox Code Playgroud)
这将工作和当前Fragments的ViewPager有方法, activityNotifiDataChange()正在调用,一切正常。
当我旋转应用程序并按下按钮做同样的事情时,activityNotifiDataChange()它被调用了,但是有一个空指针异常,因为 ArrayList<Fragment> mFragment它现在是 NULL。
这是一个显示此行为的小示例 Android Studio 项目:https ://drive.google.com/file/d/1Swqu59HZNYFT5hMTqv3eNiT9NmakhNEb/view?usp=sharing
启动应用程序并按下名为“PRESS TEST”的按钮,然后旋转设备并再次按下按钮并观看应用程序崩溃
更新解决方案感谢@GregMoens 和@EpicPandaForce
public class MainActivityPagerAdapter extends PersistenPagerAdapter<BaseFragment> {
private static int NUM_ITEMS = 3;
public MainActivityPagerAdapter(FragmentManager fm) {
super(fm);
}
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return ParentBasicInfoFragment.newInstance(0, "Page # 1");
case 1:
return ParentUTCFragment.newInstance(1, "Page # 2");
case 2:
return ParentEventsFragment.newInstance(2, "Page # 3");
default:
return null;
}
}
}
public abstract class PersistenPagerAdapter<T extends BaseFragment> extends FragmentPagerAdapter {
private SparseArray<T> registeredFragments = new SparseArray<T>();
public PersistenPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public T instantiateItem(ViewGroup container, int position) {
T fragment = (T)super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public T getRegisteredFragment(ViewGroup container, int position) {
T existingInstance = registeredFragments.get(position);
if (existingInstance != null) {
return existingInstance;
} else {
return instantiateItem(container, position);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在您的应用中看到的主要问题是您对 FragmentPagerAdapter 的工作方式的误解。我经常看到这种情况,这是由于课堂上缺乏好的 javadoc。应该实现适配器,以便 getItem(position) 在调用时返回一个新的片段实例。然后 getItem(position) 只会在寻呼机需要该位置的新实例时调用。您不应预先创建片段,然后将其传递到适配器中。您也不应该对来自您的活动或父片段(如 ParentBasicInfoFragment)的片段进行强引用。因为请记住,片段管理器正在管理片段,您还通过更新它们并保持对它们的引用来管理片段。这引起了冲突,在轮换之后,您正在尝试在未实际初始化的片段上调用 activityNotifiDataChange()(未调用 onCreate())。使用调试器和跟踪对象 ID 将确认这一点。
如果您更改代码以便 FragmentPagerAdapter 在需要时创建片段并且不存储对片段或片段列表的引用,您将看到更好的结果。
| 归档时间: |
|
| 查看次数: |
986 次 |
| 最近记录: |