android - 使用 ViewPager 进行屏幕旋转 - FragmentManager 和 FragmentPagerAdapter 的问题
问题描述
我在使用 ViewPager 处理 Fragment 时遇到了一些问题。
我所拥有的:一个包含显示一些片段
的活动(例如, )。其中一些包含一个回调接口,将在.
有一个类,用作. 和一个in来存储一些 Fragment 将显示在.MainActivity
ViewPager
MainActivity
MainActivity
FragmentPagerAdapter
ViewPager
List<Fragment>
FragmentPagerAdapter
ViewPager
我所期待的:
第一次启动,当我点击其中的一个按钮时,Fragment 调用了回调接口的方法,而 MainActivity 在其中做了一些事情。效果很好。
屏幕旋转后,我希望它的工作方式与第一次启动相同,但
NullPointerException:尝试在空引用对象(特别是片段的接口)上调用方法时打到了我的脸。
我所知道
的: -getItem(int position)
创建 Fragment 后将不会再次调用。相反,instantiateItem(ViewGroup container, int position)
将被调用。
-将在ViewPager 和FragmentManager
Fragment 中存储一些 Fragment mActive.mValues
-存储 Fragment 状态的正确方法是什么?(我在 StackOverflow 上也参考了这个和其他一些相同的主题。)
我试过和看到的:
- 覆盖instantiateItem(ViewGroup container, int position)
- 调试了 1 天。我看到当我将getSupportFragmentManager()
MainActivity 的onCreate()
方法传递给FragmentPagerAdapter
' 的超级构造函数时,在第一次启动时,它有一个“内存地址”,假设它是 '1a1a1a1'。mActive.mValues
保存了一些 Fragment的FragmentManager
“内存地址”,它们与List<Fragment>
包含它们的内容相同(假设它是 'qwertyu')。这意味着它是正确的。
但是当我旋转屏幕,getSupportFragmentManager()
再次传递时,“内存中的地址”完全不同,假设为“9f9f9f9”。并且FragmentManager
'mActive.mValues
包含一组不同的 Fragment '“内存中的地址”),尽管其中的 Fragment 数量等于第一次启动时(旋转前)保存的 Fragment 数量。
我已经List<Fragment>
用一个新的“内存地址”(假设“abababa”)添加了一个片段,具有回调接口。但是当我点击其中的按钮时,它是旋转后在FragmentManager
's中的片段(如我上面假设mActive.mValues
的那样,“内存中的地址”是'abcdeff'),并且那个没有回调接口(由于没有先设置)。并导致上面提到的NullPointerException 。MainActivity
我现在的问题是:
- 首先,如何摆脱这个问题!?最好继续使用FragmentPagerAdapter
而不是另一个类。但我也会考虑使用其他类。
- 第二,你能解释为什么FragmentManager
在旋转之前保存 Fragment 实例吗?但是在旋转之后,它会创建一个完全不同的 Fragment 实例,但仍然使用它而不是保存在List<Fragment>
?
这是代码(我想我没有instantiateItem(ViewGroup container, int position)
以正确的方式使用该方法,所以它仍然导致了问题)。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Attach the SectionsPagerAdapter to the ViewPager
SectionsPagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.viewPager);
viewPager.setAdapter(pagerAdapter);
}
//
//
//Adapter class
private class SectionsPagerAdapter extends FragmentPagerAdapter {
private static final int PAGE_HOME = 0;
private int tabCount = 1;
private List<Fragment> fragmentList = new ArrayList<>();
private List<String> fragmentTitleList = new ArrayList<>();
//private FragmentManager fragmentManager;
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
//fragmentManager = fm;
//Default HomeFragment
HomeFragment homeFragment = new HomeFragment();
//Callback interface
homeFragment.setOnCategoryFragmentChangedListener(new HomeFragment.OnCategoryFragmentChangedListener() {
//This method will be called when a button in HomeFragment is clicked
@Override
public void onAddNewCategory(String categoryName) {
addNewCategory(categoryName);
}
});
fragmentList.add(homeFragment);
fragmentTitleList.add("Home");
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return tabCount;
}
@Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
fragmentList.set(position, (Fragment) super.instantiateItem(container, position));
return fragmentList.get(position);
}
private void addNewCategory(String categoryName) {
CategoryFragment fragment = new CategoryFragment();
tabCount += 1;
fragmentList.add(fragment);
fragmentTitleList.add(categoryName);
notifyDataSetChanged();
}
}
}
请帮忙。我已经疯了2天了……!
解决方案
我相信 android 在方向更改期间会重新启动活动,从而生成多个 FragmentPagerAdapter 实例和多个 List 实例集。
我不完全理解你的问题,但我怀疑 instantiateItem 无论如何都没有做任何事情。不Fragment getItem(int pos)
覆盖instanceiteItem() 就不行吗?
推荐阅读
- python - 如何在 url 字符串中传递列表中的值
- sql-server - 配置文件中的 SQL Server 数据库端口参数
- javascript - 如何使用 javascript 检查服务器状态
- ios - iOS 10 及更早版本上的 iOS 堆栈视图问题
- wordpress - 计算单个用户的点击次数 // Wordpress
- xml - 删除命名空间并替换为另一个命名空间
- c# - C# DataTable to Json(自定义格式)
- npm - 有没有办法在每次安装或更新依赖项后运行脚本?
- java - Spring Boot 重定向网址
- java - Android Studio 不检查 query.addListenerForSingleValueEvent() 并且不返回任何内容