0

FragmentStatePagerAdapterViewPager 内にフラグメントを表示するためにa を使用しています。これらのフラグメントはすべて同じレイアウト コンテナー (a FrameLayout) に従いますが、その数は実行時に変更可能であるため、それらすべてをListフラグメントの静的に配置して渡します。そのリストをFragmentStatePagerAdapter(最初はコンストラクターを介して、その後は毎回リストとを更新するだけです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();

    }

}

これはFragment List、実行時に次の方法で作成する方法です。

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;

}

新しいフラグメントをにコミットするには: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);

}

この段階ではすべて問題ありません。指定された数のフラグメントをナビゲートすると、各フラグメントにフラグメントのコンテナがあるため、効率的にナビゲートできますMyFragment

しかし、フラグメントのビューにアクセスしようとすると、最初の2 つのフラグメントのみFrameLayoutに従って、指定されたビュー ()が返され、その後、返されたビューをループして出力しようとしました:MyFragmentnullmpa

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

これは私が得たものです:

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}
4

1 に答える 1

3

最初の 2 つのフラグメントのみで MyFragment に従って指定されたビュー (FrameLayout) を返し、その後は null を返します。

アダプターは効率的に構築されているため、すぐにアクセスできないフラグメントのビューを破棄します (アクセス可能なフラグメントは、現在表示されているフラグメントに各サイドで 1 を加えたものになります (簡単にスワイプするため)。中古setOffscreenPageLimit())。あなたの場合for、現在のページが のときにそのループを呼び出すと、0ページ01. setCurrentItem()遷移がすぐに発生しないため、呼び出しは機能しません (そのため、他のフラグメントはすぐには構築されません)。

フラグメントのビューで何をしようとしているのかわかりませんが、アプローチを再考する必要があります. とにかく、今のようにそれらを更新しようとするべきではありません。ユーザーがすぐに利用できるフラグメント (上記で言及したもの) を更新することを検討する必要があります。他のフラグメントのビューを更新しても意味がありません。ユーザーがそれらをまったく使用しない可能性があり、無駄になるからです。

次のようなコードで他のことを間違っています。

フラグメントのリストに基づくそのアダプターは、フラグメントの適切な参照が失われるため、失敗するに違いありません。getItem()アダプターは毎回メソッドを呼び出すわけではありません。場合によっては、独自にフラグメントを再作成して、リストのフラグメント参照を無効にします (特に、フラグメントのリストを静的として宣言した場合)。リストを使用する場合は、フラグメントへの参照を順番に保持してください (たとえばinstantiateItem()、アダプターのメソッドで使用される実際のフラグメントへの参照を取得できます)。

あなたがしたように、すべてのクラスフィールドを静的にしないでください。Contextビュー フィールドは への参照を保持し、それをリークする危険性があるため、ビュー フィールドを static として宣言しないでください。アダプターが使用されているフラグメントが再作成される可能性があるため、フラグメントリストを静的にしないでください。この場合、アダプター自体が再作成されますが、リストには古いコンテンツが保持されます。

于 2014-05-12T14:27:49.953 に答える