12

少し問題があります。いくつかのページを持つ ViewPager があり、FragmentStatePagerAdapter を使用してデータを処理します。たとえば、縦向きでは ViewPager 用に 20 ページあり、横向きでは ViewPager 用に 10 ページしかありません。したがって、向きを変更すると、異なるデータで新しいアダプターを作成します。

理由を少し説明します。1 つの画像を縦向きに、2 つを横向きに表示しますが、常にすべてカウントします。表示する写真が 10 枚ある場合、縦向きに 10 枚、横向きに 5 枚 (常に 2 枚) あります。

しかし、今は奇妙なバグがあります: インデックス 5 でランドスケープにいてデバイスを回すと、ViewPager の現在のページが 10 に設定されます。もう一度戻すと、5 ページにいます。ViewPage を今ページにスワイプすると10 アダプターのメソッド getItem が呼び出されることはなく、ViewPage には、横向きの 2 枚ではなく縦向きの写真が 1 枚表示されます。これはどのように起こりますか?アダプターまたは ViewPager にキャッシュはありますか? アクティビティの onCreate では、ViewPager のアダプターとデータ (パスを含む文字列のみ) がすべて新しく作成されます。では、この本当に恐ろしい「機能」を修正する方法はありますか?

ここにいくつかのコードがあります:

作成時:

    mViewPagerAdapter = new ReaderPageViewAdapter(getSupportFragmentManager(), getBaseContext(), mCurrentDocument.mPages, getResources()
                .getConfiguration().orientation);
    mPageReader = (ReaderViewPager) findViewById(R.id.pager);
    mPageReader.setAdapter(mViewPagerAdapter);

アダプタ getItem:

    public Fragment getItem(final int index) {
        final PageInfo pageInfo = mPages.get(index);
        final PageFragment pageFragment = (PageFragment) PageFragment
                .instantiate(mContext, pageInfo.mClss.getName(), pageInfo.mArgs);
        return pageFragment;
    }

さらに何か必要な場合は、教えてください。ありがとう

4

3 に答える 3

42

メソッドで FragmentActivity onSaveInstanceState() をオーバーライドし、super.onSaveInstanceState() を呼び出さないようにすることができます。

@Override
protected void onSaveInstanceState(final Bundle outState) {
    // super.onSaveInstanceState(outState);
}

使用禁止 mViewPager.setSaveEnabled(false);

それは大きなメモリリークで終わった。向きを変更するたびに、フラグメントを FragmentManager の配列に入れ、決して消去しません。そのため、向きを何度も変更すると、メモリ使用量が 100 MB を超えます。onSaveInstanceState メソッドを使用することは、私が考えるより良い方法です。

于 2013-01-29T08:41:27.257 に答える
2

私もこの問題が発生し、その理由を見つけました。

画面が回転FragmentManagerするたびに, はすべてのアクティビティがホストされたフラグメントを保持します. フラグメントは削除されません. を使用すると, を使用してフラグメントの数を確認FragmentStatePagerAdapterできます.FragmentManager.getFragments()

例: アクティビティには 4 つのフラグメントがあります. 方向を 4 回変更した後, リストのFragmentManager.getFragments()サイズは20になります!

私はいくつかの解決策を見つけました:

  1. あなたのアクティビティを呼び出さないsuper.onSaveInstanceState()でください。しかし、それは良い解決策ではないようです。フラグメントは状態を保存して復元することはできません。

  2. FragmentPagerAdapterの代わりに使用しFragmentStatePagerAdapterます。しかし、向きが変わった後、ViewPagerホストされていたフラグメントが空白になりました(他の誰かが同じ問題を抱えていますか?)。しかし、すべてのフラグメントを削除しActivity.onCreateて修正できます。このような:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentManager fm = getSupportFragmentManager();
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            FragmentTransaction transaction = fm.beginTransaction();
            for (Fragment fragment : fragments) {
                transaction.detach(fragment).remove(fragment);
            }
            transaction.commitNowAllowingStateLoss();
        }
        ...
    

    しかし、Fragment.onCreateView()2回呼び出されました。

私はまだ完璧な解決策を探しています:D

編集:
私は最終的に問題を解決しました.onStartの後にViewPagerが追加されたことが原因です. onStart に実行すると、FragmentManagerフラグメントの状態を復元しようとします。私はにトレースしましたFragmentManager, これらのコードを持っています:

com/android/support/support-fragment/24.2.1/support-fragment-24.2.1-sources.jar!/android/support/v4/app/FragmentManager.java

ハイライト行を確認してください。これf.mContainerIdは実際には私の ViewPager ID です。それから ViewPager にフラグメントビューを追加しようとします. 私の場合, ViewPager はまだ追加されていません. なのでブランクになります. しかしフラグメントの状態はATTACHED. でFragmentPagerAdapter.instantiateItem(), フラグメントが追加された場合, フラグメントを実行するだけですattach. しかし, フラグメントはすでに結合されています. したがって, 何もしません :(

ViewPager をアクティビティ レイアウト XML に追加しましたが、修正されました。

ハッピーコーディング:D

于 2016-10-25T16:24:36.283 に答える
-1

viewPager.setonpagechangelistener で使用し、require コードをアプリケーションに適用するために実装するだけで、

http://developer.android.com/reference/android/support/v4/view/ViewPager.html

于 2012-12-17T10:18:05.067 に答える