12

フラグメントに関して非常に奇妙な問題があります。最新のサポートライブラリを使用しています。また、GoogleがIOSCHEDプロジェクトで使用しているのと同様のコードを使用しています

しかし、ローテーション後のアクティビティの再現に問題があります。アクティビティが破棄されて再度作成された後、フラグメントトランザクションを管理するためのメソッドを呼び出します(onStartメソッド内)。この行は1回だけ呼び出されますが、フラグメントが2回作成されます。

これは私の活動方法です:

public abstract class SinglePaneActivity extends FragmentActivity
{
    @Override
    protected void onStart()
    {
        super.onStart();

        if(mFragment == null)
        {
            mFragment = onCreatePane();     
            mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));

            Log.w(TAG, "Fragment creation counter = " + createCounter);
            createCounter++;

            getSupportFragmentManager() 
            .beginTransaction()
            .add(R.id.root_container,mFragment)
            .commit();
        }
    }

    @Override
    protected void onStop()
    {
        Log.i(TAG, "onStop");
        if(mFragment != null)
        {
            getSupportFragmentManager()
            .beginTransaction()
            .remove(mFragment)
            .commit();

            mFragment = null;
        }
        super.onStop();
    }
}

と私のログ:

--Start of application--
11-18 13:26:37.050: I/SinglePaneActivity(19040): onCreate
11-18 13:26:37.050: I/SinglePaneActivity(19040): onStart
11-18 13:26:37.055: W/SinglePaneActivity(19040): replacing fragment, counter = 1
11-18 13:26:37.075: I/MyFragment(19040): onCreate
11-18 13:26:37.110: I/MyFragment(19040): onActivityCreated
--Rotating the device--
11-18 13:26:39.600: I/SinglePaneActivity(19040): onStop
11-18 13:26:39.600: I/SinglePaneActivity(19040): onDestroy
11-18 13:26:39.605: I/MyFragment(19040): onDestroy
11-18 13:26:39.755: I/MyFragment(19040): onCreate
11-18 13:26:39.755: I/SinglePaneActivity(19040): onCreate
11-18 13:26:39.790: I/MyFragment(19040): onActivityCreated
11-18 13:26:39.800: I/SinglePaneActivity(19040): onStart
11-18 13:26:39.800: W/SinglePaneActivity(19040): replacing fragment, counter = 2
11-18 13:26:39.810: I/MyFragment(19040): onCreate
11-18 13:26:39.815: I/MyFragment(19040): onActivityCreated
--Rotating the device back--
11-18 13:36:47.060: I/SinglePaneActivity(19040): onStop
11-18 13:36:47.060: I/SinglePaneActivity(19040): onDestroy
11-18 13:36:47.060: I/MyFragment(19040): onDestroy
11-18 13:36:47.065: I/MyFragment(19040): onDestroy
11-18 13:36:47.130: I/MyFragment(19040): onCreate
11-18 13:36:47.130: I/MyFragment(19040): onCreate
11-18 13:36:47.130: I/SinglePaneActivity(19040): onCreate
11-18 13:36:47.140: I/MyFragment(19040): onActivityCreated
11-18 13:36:47.150: I/MyFragment(19040): onActivityCreated
11-18 13:36:47.150: I/SinglePaneActivity(19040): onStart
11-18 13:36:47.150: W/SinglePaneActivity(19040): replacing fragment, counter = 3
11-18 13:36:47.160: I/MyFragment(19040): onCreate
11-18 13:36:47.160: I/MyFragment(19040): onActivityCreated
--Exiting the app--
11-18 13:36:48.880: I/SinglePaneActivity(19040): onStop
11-18 13:36:48.885: I/SinglePaneActivity(19040): onDestroy
11-18 13:36:48.885: I/MyFragment(19040): onDestroy
11-18 13:36:48.890: I/MyFragment(19040): onDestroy
11-18 13:36:48.890: I/MyFragment(19040): onDestroy

そのため、各ローテーション後にフラグメントの数が増えています。

回転後、onStartメソッドに移動する前にフラグメントを復元し、onStartメソッドは同じフレームレイアウトコンテナに2番目の同じフラグメントを作成します。しかし、どこで最初のフラグメントを復元しますか?私はそれを避けたい。または、「if」を変更して、すでに作成されているかどうかをテストする必要がありますか?しかし、私はそれを決定する方法を知りません。nullテストは役に立たないようです。

add()また、メソッドをに置き換えて、小さな回避策を作成しましたreplace()。その後、フラグメントの数は増えず、新しいフラグメントがonStartメソッドで作成される前に、各フラグメントが破棄されます。しかし、これは、onCreateメソッドでいくつかのバックグラウンドプロセスを開始するいくつかのフラグメントで深刻な問題を引き起こします...

私を助けてください...私はそれをどうしたらいいのか本当にわかりません。アドバイスやアイデアをありがとうございました!

4

3 に答える 3

24

さて私は解決策を見つけました。フラグメントマネージャーを使用してコードをonStartからonCreateに移動し、のnull値を確認する必要がありsavedInstanceStateました。savedInstanceStateさて、それが自動的に保存され、復元されることを知りませんでした。知っておくと良い!

編集:それを完全に正しくするために、つまり、savedInstanceStateがnullでないときにフラグメントを復元するには、次のようにする必要があります。

    if(savedInstanceState == null)
    {
        mFragment = onCreatePane();     
        mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));

        getSupportFragmentManager() 
        .beginTransaction()
        .add(R.id.root_container,mFragment)
        .commit();
    } 
    else
    {
        mFragment = getSupportFragmentManager().findFragmentById(R.id.root_container);
    }
于 2011-11-21T13:04:33.727 に答える
1

同様の問題が発生しましたが、親フラグメントから子フラグメントを追加していて、重複する子フラグメントが表示されていました。親フラグメントに追加しようとしていたonStartので、では使用できない親ビューにアクセスできましたonCreate。したがって、コードをに移動する代わりにonCreate、に移動しましたonActivityCreated。そのメソッドは親ビューにアクセスできsavedInstanceState、フラグメントがすでに自動的に追加されているかどうかを確認するための変数にもアクセスできます。アクティビティのビューはで使用できるため、アクティビティからフラグメントを追加する場合、これは問題になりませんonCreate


何らかの理由でフラグメントを追加する必要がある場合、onStartまたは利用できない別の場所にフラグメントを追加する必要がある場合は、次savedInstanceStateの方法があります。質問の元のonStartコードを使用しています...

   if(mFragment == null)
    {
        mFragment = onCreatePane();     
        mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));

        Log.w(TAG, "Fragment creation counter = " + createCounter);
        createCounter++;

        getSupportFragmentManager() 
        .beginTransaction()
        .add(R.id.root_container,mFragment)
        .commit();
    }

...フラグメントではreplaceなく可能性があります:add

   if(mFragment == null)
    {
        mFragment = onCreatePane();     
        mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));

        Log.w(TAG, "Fragment creation counter = " + createCounter);
        createCounter++;
    }

    getSupportFragmentManager() 
    .beginTransaction()
    .replace(R.id.root_container,mFragment)
    .commit();

次に、フラグメントがすでに自動的に追加されている場合は、新しいフラグメントがビュー内のフラグメントを置き換えるだけです。

于 2014-09-17T04:08:05.843 に答える
-1

または、フラグメントがバックスタックにない場合:setRetainInstance(true);

于 2012-04-04T16:00:25.483 に答える