2017-02-16 71 views
0

只是片段的许多问题之一。 在Activity.onCreate()方法中,我正在初始化一个ViewPager,其中有两个FragmentsViewPager的第二个片段尚未实例化

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

只是尝试使用'FragmentPagerAdapter'而不是'FragmentStatePagerAdapter' –

+0

@EduardoHerzer任何想法,为什么这应该解决这个问题? – fillobotto

+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(); 

然后在onCreateViewManualFragment,得到参数:

Object obj = (Object) getArguments().getSerializable("obj"); 
String str = getArguments().getString("str"); 

而且做w你必须做的恨。

编辑2:

由于OP想要另一种方法,这里有云......

做这样的事情的答案:https://stackoverflow.com/a/24343211/2174489

这样你就不会从另一个片段访问视图超出原来的范围。我不喜欢像((Fragment) adapter.getItem(1)).getView().findViewById(...)这样的想法。我宁愿做((Fragment) adapter.getItem(1)).setTextViewText(...)

然后,在setTextViewText你可以测试你的视图是否为空。如果为null,保存在字符串中的全局变量:

public void setTextViewText(String value){ 
    if (mTextView == null) 
     myGlobalValue = value; 
    else 
     mTextView.setText(value); 
} 

然后在onCreateView,你可以设置这个值:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    ... 
    if (myGlobalValue != null) 
     mTextView.setText(myGlobalValue); 
    ... 
} 

让我知道这是否解决了问题。

+0

有趣。我会更新测试版本,看看问题是否再次出现。 – fillobotto

+0

不幸的是问题依然存在。这听起来更像是这个片段被插入,但它没有附加到活动 – fillobotto

+0

@fillobotto我编辑了答案。也许你可以尝试这种方法 –

相关问题