FragmentStatePagerAdapter返回null意见 [英] FragmentStatePagerAdapter returns null views

查看:229
本文介绍了FragmentStatePagerAdapter返回null意见的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 FragmentStatePagerAdapter ,以一个ViewPager中显示的碎片,这些碎片服从相同的布局容器(的FrameLayout ),但它的数量超过运行时间变化的,所以,我把他们都变成碎片的静态列表,并通过该列表的 FragmentStatePagerAdapter (以后每次我刚刚更新列表第一时间通过它的构造与和 notifydatasetchanged

 公共类MyPageAdapter扩展FragmentStatePagerAdapter {    公共静态列表<片断> myFragments =新的ArrayList<片断>();
    公共MyPageAdapter(FragmentManager fragmentManager,列表与LT;片断>片段){
        超(fragmentManager);        myFragments =片段;    }    公共片段的getItem(int i)以{        返回myFragments.get(ⅰ);    }    @覆盖
    公众诠释的getCount(){         返回myFragments.size();    }}

现在,这是我创建的方式片段列表期间运行时间:

 公开名单<片断>分段(INT NUM){// NUM:碎片我想创造数        清单<片断>碎片=新的矢量<片断>();        的for(int i = 0; I<民;我++){
            包页面=新包();
            page.putInt(指数,我);
            fragments.add(Fragment.instantiate(mContext,MyFragment.class.getName(),页));
        }        返回片段;}

提交的新的片段 ViewPager

 公共静态PagerAdapter广告;
公共静态ViewPager sViewPager;
私有静态MyPageAdapter MPA;公共无效display_fragments(INT I,布尔INIT){    如果(初始化){//初始化意味着我们在第一次初始化和它放在这里仅在第一时间
        清单<片断>片段=粉碎(ⅰ);
        MPA =新MyPageAdapter(getChildFragmentManager(),片段);
        sViewPager =(ViewPager)view.findViewById(R.id.my_view_pager);
    }其他{//这里是我们的情况
        清单<片断>片段=粉碎(ⅰ);
        MyPageAdapter.myFragments =片段;
        mpa.notifyDataSetChanged();
    }    广告= MPA;
    sViewPager.setAdapter(广告);
    sViewPager.setCurrentItem(0);}

在这个阶段一切正常,如果我去导航,通过片段代表特定的NUM将与每个片断有效地浏览了 MyFragment 片段的容器。

但在尝试访问片段的视图时,它返回指定的View(的FrameLayout )根据 MyFragment 在第一的两个片段只,之后返回,我试图通过 MPA :

 为(INT G = 0; G< mpa.getCount(); G ++){
    的System.out.println(mpa.getItem(G));
}

这是我得到了什么:

  8月5日至一十二日:36:10.175:我/的System.out(1062):MyFragment {53535b8c#1 ID = 0x7f06005e}
八月五日至12日:36:10.175:我/的System.out(1062):MyFragment {540e71b4#0 ID = 0x7f06005e}
八月五日至12日:36:10.175:我/的System.out(1062):MyFragment {} 540e7298
八月五日至12日:36:10.175:我/的System.out(1062):MyFragment {} 540e737c
八月五日至12日:36:10.175:我/的System.out(1062),:MyFragment {} 540e7460


解决方案

  

它返回根据MyFragment在指定的视图(的FrameLayout)
  前两个片段只,之后返回null


该适配器内置有效率,因此破坏不能被访问马上碎片的意见(可访问的片段会在每边(为了便于刷卡当前可见的一加一),这除非持有你使用 setOffscreenPageLimit())。在你的情况,如果你调用了 0 循环时,当前页面,你会得到的唯一有效的片段意见页面 0 1 。调用 setCurrentItem()不起作用,因为过渡不会立即发生(因此其他片段没有建立正确的距离)。

我不知道你想用碎片的意见,做什么,但你需要重新考虑你的方法。你不应该试图更新它们就像你现在反正,你应该看看更新是提供给用户马上片段(那些我在上面提到)。更新其他片段的意见并不作出的用户可能不会在使用它们这将是浪费的感觉。

您在做其他事情错在你的code,如:

根据碎片的名单上适配器注定要失败,因为你会失去片段的恰当引用。该适配器不叫的getItem()方法每次,在某些情况下,它会重新创建自己的片段让你列出片段引用无效(尤其是当你声明的片段的名单静态)。如果你要使用列表一定要保持以片段的引用(例如,你可以得到在实际使用的片段引用 instantiateItem()适配器的方法)。

不要让每类字段静态像你这样。因为他们抱到上下文的引用,你的风险就漏水,你不应该声明视场为静态。该片段列表不应作出静态的,因为其中使用的适配器的片段可能会被重新创建时,在这种情况下,适配器本身将被重新创建,但是您的列表将保持旧的内容

I'm using a FragmentStatePagerAdapter in order to display fragments within a ViewPager, all of these Fragments obey the same layout container(a FrameLayout) but it's number is changeable over run-time, So that I put all of them into a static List of fragments and pass that list to the FragmentStatePagerAdapter(first time through it's constructor and each time after that I just update the list and notifydatasetchanged):

public class MyPageAdapter extends FragmentStatePagerAdapter {

    public static List<Fragment> myFragments = new ArrayList<Fragment>();
    public MyPageAdapter(FragmentManager fragmentManager, List<Fragment> fragments) {
        super(fragmentManager);

        myFragments = fragments;

    }

    public Fragment getItem(int i) {

        return myFragments.get(i);

    }

    @Override
    public int getCount() {

         return myFragments.size();

    }

}

Now this is the way I create a Fragment List during the run-time by:

public List<Fragment> fragmenting(int num) { // num: the Number of fragments i wanna create 

        List<Fragment> fragments = new Vector<Fragment>();

        for(int i =0; i < num ; i++){
            Bundle page = new Bundle();
            page.putInt("index", i);
            fragments.add(Fragment.instantiate(mContext, MyFragment.class.getName(), page));
        }

        return fragments;

}

and to commit the new Fragments to the ViewPager:

public static PagerAdapter ad;
public static ViewPager sViewPager;
private static MyPageAdapter mpa;

public void display_fragments(int i, boolean init) {

    if(init){ // init means we are in the first initialization and it goes here only at the first time
        List<Fragment> fragments = fragmenting(i);
        mpa = new MyPageAdapter(getChildFragmentManager(), fragments);
        sViewPager = (ViewPager) view.findViewById(R.id.my_view_pager);
    }else{ // is our case here
        List<Fragment> fragments = fragmenting(i);
        MyPageAdapter.myFragments = fragments;
        mpa.notifyDataSetChanged();
    }

    ad = mpa;
    sViewPager.setAdapter(ad);
    sViewPager.setCurrentItem(0);

}

at this stage everything in OK, and if I go and navigate through the specifid num of fragments it will navigate efficiently with each fragment has the container of MyFragment fragment.

but when trying to access the Views of the fragments, It returns the specified View (FrameLayout) according to MyFragment in the first two fragments only and after that it returns null, I tried to print out the returned Views by looping through mpa :

for(int g =0; g < mpa.getCount(); g++){
    System.out.println(mpa.getItem(g));
}

and this is what I got:

05-12 08:36:10.175: I/System.out(1062): MyFragment{53535b8c #1 id=0x7f06005e}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e71b4 #0 id=0x7f06005e}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e7298}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e737c}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e7460}

解决方案

It returns the specified View (FrameLayout) according to MyFragment in the first two fragments only and after that it returns null

The adapter is built to be efficient so it destroys the views of the fragments that can't be accessible right away(the accessible fragments would be the current visible one plus one on each side(for easy swipe), this holds unless you've used setOffscreenPageLimit()). In your case if you call that for loop when the current page is 0 you'll get valid fragment views for only page 0 and 1. Calling setCurrentItem() doesn't work because the transition doesn't happen right away(so the other fragments are not built right away).

I don't know what you're trying to do with the views of the fragments, but you'll need to rethink your approach. You shouldn't be trying to update them like you do now anyway, you should look to update the fragments that are available to the user right away(the ones I mention above). Updating the views of the other fragments doesn't make sense as the user might not use them at all which would be wasteful.

You're doing other things wrong in your code like:

That adapter based on a list of fragments is bound to fail because you'll lose the proper references of the fragments. The adapter doesn't call the getItem() method every time, in some cases it will recreate the fragments on its own making you list fragment reference invalid(especially as you declared the list of fragments as static). If you're going to use a list make sure you keep the references to the fragments in order(for example you could get references to the actual fragments used in the instantiateItem() method of the adapter).

Don't make every class field static like you did. You shouldn't declare view fields as static because they hold a reference to the Context and you risk leaking it. The fragment list shouldn't be made static because the fragment where the adapter is used might get recreated, in this case the adapter itself will be recreated, your list however will hold the old content.

这篇关于FragmentStatePagerAdapter返回null意见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆