Вопрос по android – Fragment.isAdded возвращает true после удаления фрагмента из контейнера.

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 деятельности я загружаю Fragment_A в frameLayoutA и Fragment_B в frameLayoutB.

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.isAdded () возвращает true после выполнения операции fragB.remove (). Во время 2-ой операции меню fragB.isAdded () возвращает false, и fragB.add () выполняется, и FragmentB отображается в frameLayoutA.

Я понимаю, что commit - это асинхронная операция. isAdded возвращает true, потому что commit является асинхронным, и операция commit удаления не выполняется до момента вызова fragB.isAdded (). Это правда?

Просьба предложить возможное решение или подход к решению проблемы.

С Уважением, Vibhor

Ваш Ответ

2   ответа
26

транзакция совершается асинхронно. Если вы хотите убедиться, что все транзакции завершены перед выполнениемisAdded, бежать:

getFragmentManager().executePendingTransactions();

Из документации дляexecutePendingTransactions():

After a FragmentTransaction is committed with FragmentTransaction.commit(), it is scheduled to be executed asynchronously on the process's main thread. If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.

Итак, ваш код должен выглядеть так:

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");
}

Обратите внимание, также исправлено удаление фрагмента А.

Error: User Rate Limit Exceeded vibhor
0

private void commitFragmentTransaction(final FragmentTransaction ft, boolean allowStateLoss, boolean now) {
    if (ft == null || ft.isEmpty()) {
        return;
    }

    if (allowStateLoss) {
        if (now) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                ft.commitNowAllowingStateLoss();
            } else {
                ft.commitAllowingStateLoss();
                mFragmentManager.executePendingTransactions();
            }
        } else {
            ft.commitAllowingStateLoss();
        }
    } else {
        if (now) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                ft.commitNow();
            } else {
                ft.commit();
                mFragmentManager.executePendingTransactions();
            }
        } else {
            ft.commit();
        }
    }
}

commitNow () и commitNowAllowingStateLoss () добавлены на уровне API 24

Вызов commitNow предпочтительнее вызова commit (), за которым следует executePendingTransactions (), поскольку последний будет иметь побочный эффект при попытке зафиксировать все ожидающие транзакции, независимо от того, является ли это желаемым поведением или нет.

Похожие вопросы