9

私は2つを保持するViewPager(extends FragmentPagerAdapter)を持っていますFragments。必要なのは、それらの間をスワイプしたときにListView、それぞれを更新することです。Fragmentこのために、ViewPager.OnPageChangeListenerインターフェイス(つまりonPageScrollStateChanged)を実装しました。Fragmentsへの参照を保持するために、を使用しHashTableます。Fragmentsinメソッドへの参照を格納HashTableします。getItem()

  @Override
        public Fragment getItem(int num) {
            if (num == 0) {
                Fragment itemsListFragment = new ItemsListFragment();
                mPageReferenceMap.put(num, itemsListFragment);
                return itemsListFragment;
            } else {
                Fragment favsListFragment = new ItemsFavsListFragment();
                mPageReferenceMap.put(num, favsListFragment);
                return favsListFragment;
            }
        }

Fragmentしたがって、あるトリガーから別のトリガーにスワイプすると、両方で必要なメソッドを呼び出すためonPageScrollStateChangedにを使用するトリガー(更新):HashTableFragments

 public void refreshList() {
        ((ItemsListFragment) mPageReferenceMap.get(0)).refresh();
        ((ItemsFavsListFragment) mPageReferenceMap.get(1)).refresh();
    }

orientation changeイベントが発生するまで、すべてがうまくいきます。refresh()その後、メソッドのコードは次のようになります。

public void refresh() {
        mAdapter.changeCursor(mDbHelper.getAll());
        getListView().setItemChecked(-1, true); // The last row from a exception trace finishes here (my class).
    }

結果IllegalStateException

java.lang.IllegalStateException: Content view not yet created
        at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
        at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
        at ebeletskiy.gmail.com.passwords.ui.ItemsFavsListFragment.refresh(ItemsFavsListFragment.java:17)

Contentビューが実際に作成されていないと仮定して、メソッドのboolean変数をに設定し、条件を使用して呼び出すかどうかを指定しました。これにより、アクティビティビューとコンテンツビューが正常に作成されたことがわかります。onActivityCreated()trueif/elsegetListView()

次に、デバッグを行って、いつFragmentPagerAdapter呼び出されるかを確認しましたが、イベントgetItem()後にメソッドが呼び出されません。したがって、oldへの参照を保持しているorientation changeように見えます。これは私の仮定です。ViewPagerFragments

それで、私が現在への適切な参照を使用できるように、を再度ViewPager呼び出すように強制する方法はありますか?他の解決策かもしれませんか?どうもありがとうございます。getItem()Fragments

4

3 に答える 3

5

次に、FragmentPagerAdapterがgetItem()を呼び出すタイミングを確認するためにデバッグしていましたが、方向変更イベントの後でメソッドが呼び出されないことがあります。つまり、ViewPagerは古いフラグメントへの参照を保持しているように見えます。

フラグメントが構成変更されているのと同じように、フラグメントは自動的に再作成されます。例外は、を使用setRetainInstance(true)した場合です。この場合、それらは以前と同じフラグメントオブジェクトである必要があります。

それで、ViewPagerにgetItem()を再度呼び出すように強制する方法はありますか?それで、現在のフラグメントへの適切な参照を使用できますか?

そこにあるフラグメントの何が問題になっていますか?

于 2012-09-03T22:11:53.097 に答える
0

この問題の解決策を探すのに数日を費やしましたが、多くの点がわかりました。

  • FragmentPagerAdapterの代わりに使用FragmentStatePagerAdapter

  • FragmentStatePagerAdapterの代わりに使用FragmentPagerAdapter

  • POSITION_NONEFragmentPagerAdapterのgetItemPositionオーバーライドで戻る

  • フラグメントの動的な変更が必要な場合は FragmentPagerAdapter を使用しないでください

  • そして、多くの多くの他の...

私のアプリでは、Eugeneのように、作成されたフラグメントのインスタンスを自分で管理しました。私はそれをHashMap<String,Fragment>特殊なクラス内の 1 つに保持しているため、フラグメントが解放されることはなく、アプリが高速化されます (ただし、より多くのリソースを消費します)。

問題は、タブレット (および電話) を回転させたときでした。そのgetItem(int)フラグメントに対して が呼び出されなくなり、変更できませんでした。

本当に解決策が見つかるまで本当に多くの時間を費やしたので、何度も助けてくれるStackOverflowコミュニティと共有する必要があります...

この問題の解決策は、見つけるのが大変ですが、非常に簡単です。

FragmentPagerAdapter extends のコンストラクターで FragmentManager への参照を保持するだけです。

public class Manager_Pager extends FragmentPagerAdapter {

    private final FragmentManager mFragmentManager;
    private final FragmentActivity mContext;

    public Manager_Pager(FragmentActivity context) {

        super( context.getSupportFragmentManager() );

        this.mContext = context;
        this.mFragmentManager = context.getSupportFragmentManager();
    }

    @Override
    public int getItemPosition( Object object ) {

// here, check if this fragment is an instance of the
//   ***FragmentClass_of_you_want_be_dynamic***

        if (object instanceof FragmentClass_of_you_want_be_dynamic) {

// if true, remove from ***FragmentManager*** and return ***POSITION_NONE***
//   to force a call to ***getItem***

            mFragmentManager.beginTransaction().remove((Fragment) object).commit();
            return POSITION_NONE;
        }

        //don't return POSITION_NONE, avoid fragment recreation.
        return super.getItemPosition(object);
    }

    @Override
    public Fragment getItem( int position ) {


        if ( position == MY_DYNAMIC_FRAGMENT_INDEX){

            Bundle args = new Bundle();
            args.putString( "anything", position );
            args.putString( "created_at", ALITEC.Utils.timeToStr() );

            return Fragment.instantiate( mContext, FragmentClass_of_you_want_be_dynamic.class.getName(), args );

        }else

        if ( position == OTHER ){

            //...

        }else

        return Fragment.instantiate( mContext, FragmentDefault.class.getName(), null );

    }
}

それで全部です。そして、それは魅力のように機能します...

于 2014-07-08T03:57:03.910 に答える