片段的众多问题之一。
在Activity.onCreate()
方法中,我初始化了ViewPager
,其中包含两个Fragments
。
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setOffscreenPageLimit(1);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new AutoFragment(), getString(R.string.song_header_automatic));
adapter.addFragment(new ManualFragment(), getString(R.string.song_header_manual));
adapter.notifyDataSetChanged();
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
之后,我需要对ViewPager的第二个片段中的View
执行操作。
((Fragment) adapter.getItem(1)).getView().findViewById(...)
但它给NPE,因为用户从不浏览到第二个片段,因此它还没有附加。以相同的方式访问第一个片段的元素不会产生任何问题。
不应该setOffscreenPageLimit(1)
方法告诉Android还渲染第二个片段吗?
我也尝试不在调用适配器中调用destroyItem
的超级方法,但没有运气,因为问题是片段甚至没有被初始化。
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {}
}
如何强制它以便渲染不可见的片段?
注意:此问题有时仅发生在应用用户身上,我无法重现。只有在我遇到这个问题后,我认为所有这些都是在正确的生命周期事件之后执行错误操作。
答案 0 :(得分:0)
作为FragmentStatePagerAdapter
的文档:
当有大量的寻呼机时,此版本的寻呼机更有用 页面,更像列表视图。当页面不可见时 用户,他们的整个片段可能会被破坏,只保留 保存了该片段的状态。这允许寻呼机保持很多 与每个访问页面相关联的内存较少 FragmentPagerAdapter的代价可能是更多的开销 在页面之间切换。
您可以尝试使用FragmentPagerAdapter
。
编辑:
由于它发生在少数设备上,我猜它是一个低内存设备。
您可能会尝试重新加载第二个片段,并将args传递给它。
在适配器上,实现一个替换片段的方法:
public void replaceFragment(int index, Fragment fragment, String title) {
mFragmentList.set(index, fragment);
mFragmentTitleList.add(index, title);
}
如果要使用新数据重新加载第二个片段,请执行以下操作:
Bundle fragmentArgs = new Bundle();
fragmentArgs.putSerializable("obj", obj); //data you want to pass
fragmentArgs.putString("str", str); //data you want to pass
ManualFragment manualFragment = new ManualFragment();
manualFragment.setArguments(fragmentArgs);
adapter.replaceFragment(1, manualFragment, getString(R.string.song_header_manual));
adapter.notifyDataSetChanged();
然后在onCreateView
的{{1}},获取参数:
ManualFragment
做任何你必须做的事。
编辑2:
由于OP想要另一种方法,这里就是......
做这样的回答:https://stackoverflow.com/a/24343211/2174489
这样您就不会从原始范围之外的其他片段访问视图。我不喜欢像Object obj = (Object) getArguments().getSerializable("obj");
String str = getArguments().getString("str");
这样的想法。我宁愿做((Fragment) adapter.getItem(1)).getView().findViewById(...)
。
然后,在((Fragment) adapter.getItem(1)).setTextViewText(...)
,您可以测试您的视图是否为空。如果为null,则将字符串保存在全局变量中:
setTextViewText
然后在public void setTextViewText(String value){
if (mTextView == null)
myGlobalValue = value;
else
mTextView.setText(value);
}
,您可以设置该值:
onCreateView
如果能解决问题,请告诉我。