10

以下のレイアウトのアクティビティがあります

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

    <FrameLayout
        android:id="@+id/frameLayoutA"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1" >
    </FrameLayout>
    <FrameLayout
        android:id="@+id/frameLayoutB"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1" >
    </FrameLayout>
</LinearLayout>

アクティビティの onCreate で、frameLayoutA に Fragment_A を、frameLayoutB に Fragment_B を読み込みます。

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    fmA=(FrameLayout) findViewById(R.id.frameLayoutA);
    fmB=(FrameLayout) findViewById(R.id.frameLayoutB);

    fragA=new FragmentA();
    fragB=new FragmentB();
    fragC=new FragmentC();
    addFragmentsInActivity(R.id.frameLayoutA,fragA);
    addFragmentsInActivity(R.id.frameLayoutB,fragB);
}

public void addFragmentsInActivity(int id, Fragment fragment)
{
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.add(id, fragment);
    fragmentTransaction.commit();
}

メニュー操作でFragment_BをframeLayoutAに、Fragment_CをframeLayoutBに読み込みたい。メニュー操作は次のとおりです。

    removeFragmentsInActivity(R.id.frameLayoutB,fragB);
    addFragmentsInActivity(R.id.frameLayoutB,fragC);
    if(!fragB.isAdded()){
            Log.e("check", "fragB already removed from frameLayoutB");
        removeFragmentsInActivity(R.id.frameLayoutB,fragB);
        addFragmentsInActivity(R.id.frameLayoutA,fragB);
    }
    else{
        Log.e("check", "fragB already added");
    }    

    public void removeFragmentsInActivity(int id, Fragment fragment)
    {
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.remove(fragment);
        fragmentTransaction.commit();
    }

Fragment_B は frameLayoutA に表示されません。frameLayoutA は Fragment_A を示しています。メニュー操作を再度クリックすると Fragment_B がロードされます。

デバッグ fragB.remove() 操作が完了した後、 fragB.isAdded() が true を返した後に発見しました。2 番目のメニュー操作中に fragB.isAdded() が false を返し、fragB.add() が実行され、FragmentB が frameLayoutA に表示されます。

コミットは非同期操作であることを理解しています。isAdded は true を返します。これは、コミットが非同期であり、fragB.isAdded() が呼び出されるまでコミットの削除操作が行われないためです。本当ですか?

問題を解決するための可能な解決策またはアプローチを親切に提案してください。

よろしく、バイバー

4

2 に答える 2

27

はい、トランザクションは非同期でコミットされます。を実行する前にすべてのトランザクションが終了していることを確認するには、次isAddedを実行します。

getFragmentManager().executePendingTransactions();

のドキュメントからexecutePendingTransactions():

FragmentTransaction が FragmentTransaction.commit() でコミットされた後、プロセスのメイン スレッドで非同期に実行されるようにスケジュールされます。このような保留中の操作をすぐに実行したい場合は、この関数を (メイン スレッドからのみ) 呼び出すことができます。すべてのコールバックとその他の関連する動作はこの呼び出し内から行われることに注意してください。そのため、これがどこから呼び出されるかについて注意してください。

したがって、コードは次のようになります。

removeFragmentsInActivity(R.id.frameLayoutB,fragB);
addFragmentsInActivity(R.id.frameLayoutB,fragC);
getFragmentManager().executePendingTransactions();
if(!fragB.isAdded()){
        Log.e("check", "fragB already removed from frameLayoutB");
    removeFragmentsInActivity(R.id.frameLayoutA,fragA);
    addFragmentsInActivity(R.id.frameLayoutA,fragB);
}
else{
    Log.e("check", "fragB already added");
}

フラグメント A の削除も修正されたことに注意してください。

于 2012-05-23T07:52:39.597 に答える