Fragment與BackStack運作流程?

public class MainBizActivity extends FragmentActivity extends Callback{

protected void onCreate(Bundle savedInstanceState) {

...

if (fragment == null) {

onAdd(R.id.fragment_container,new MainBizFragment());

}

}

//屬於介面callback的方法

public void onAdd(int container,Fragment fragment) {

if (thisFragment == null) {

fm.beginTransaction()

.add(container, fragment)

.commit();

}

}

//屬於介面callback的方法

public void onReplace(int container,Fragment fragment ) {

Fragment thisFragment = (Fragment) fm.findFragmentById(container);

if (thisFragment != null) {

fm.beginTransaction()

.replace(container, fragment)

.addToBackStack(fragment.getClass().getName())

.commit();

} else

onAdd(container, fragment);

}

}

public class MainBizFragment extends Fragment {

public View onCreateView(...) {

//馬上開啟 MapFragment,加入到 MainBizFragment的布局中

Callback.onAdd(R.id.content_container, new MapFragment());

}

}

public class MapFragment extends Fragment {

public View onCreateView(...) {

v.findViewById(R.id.button_go).setOnClickListener(new View.OnClickListener() {

//按鈕啟動 SettingFragment,代替 MainBizFragment

@Override

public void onClick(View v) {

Callback.onReplace(R.id.fragment_container,new SettingFragment());

}

}

public void onReplaceNotBackstack(int container,Fragment fragment ) {

if (thisFragment != null) {

fm.beginTransaction()

.replace(container, fragment)

.commit();

} else {

onAdd(container, fragment);

}

現在問題是:從SettingFragment中後退,MapFragment會不見了。

由於content_container 需要更換為別的Fragment,也就沒有addToBackStack( )。

怎樣才能使MapFragment回來呢?

還是因為這一套邏輯本身出問題呢?


謝邀

想必題主對於addToBackStack( )這個方法理解不深

這裡先解釋下這個方法的作用

我們開啟一個新的fragment 用下面這種方式

FragmentManager manager = getSupportFragmentManager();
AFragment fragment = new AFragment();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(viewId, fragment);
transaction.addToBackStack();
transaction.commit();

其中對fragment的操作是下面這個方法

transaction.replace(viewId, fragment);

這個方法可以分解成

transaction.add(viewId, fragment);
transaction.show(fragment);
transaction.hide(preFragment);
transaction.remove(preFragment);

這兩種方式是等效的,只是下面的看起來更直白

那麼addToBackStack()這個方法究竟做了什麼?

調用addToBackStack()後按back鍵

AFragment 消失,preFragment又出現了,你在fragment的生命周期中加入log就會發現,AFragment銷毀,preFragment被重新創建

其實addToBackStack()記錄的是一個transaction的操作記錄,當你按back鍵時,相當於調用了

transaction.add(viewId, preFragment);
transaction.show(preFragment);
transaction.hide(fragment);
transaction.remove(fragment);

即transaction操作了100個fragment的行為,一旦按back鍵,會讀取這100個記錄,按反方向調用一次 add 變成remove hide 變成show

現在你明白為什麼MapFragment不見了吧

Callback.onReplace(R.id.fragment_container,new SettingFragment());

這個封裝方法記錄的只是SettingFragment代替了MainBizFragment,因此按back鍵只是反方向調用一次,並沒有保存MainBizFragment中已經開啟MapFragment這一狀態

addToBackStack()保存的是一系列針對一個fragmentTransaction的操作記錄

addToBackStack()保存的是一系列針對一個fragmentTransaction的操作記錄

addToBackStack()保存的是一系列針對一個fragmentTransaction的操作記錄

重要的話要說三遍

那麼你的問題如何解決?

你只需保存已經開啟MapFragment的這一狀態就可以了,在MainBizFragment的onResume(或其他更適合的生命周期函數)中判斷一下保存的條件,選擇性的開啟MapFragment即可

或者,靈活運用 add remove hide show 這幾個方法,可以免除重複創建的開銷


@SamuraiSong 前輩說的已經很清楚了,Google官方的文檔中的對addToBackStack()有比較詳細的說明,建議有時間在詳細的看一下「Fragment」這一節。

Keep in mind that when you perform fragment transactions, such as replace or remove one, it"s often appropriate to allow the user to navigate backward and "undo" the change. To allow the user to navigate backward through the fragment transactions, you must call addToBackStack() before you commit the FragmentTransaction.

Note: When you remove or replace a fragment and add the transaction to the back stack, the fragment that is removed is stopped (not destroyed). If the user navigates back to restore the fragment, it restarts. If you do not add the transaction to the back stack, then the fragment is destroyed when removed or replaced.

原文鏈接:http://developer.android.com/training/basics/fragments/fragment-ui.html#Replace


關於fragmentmanager的源碼分析可以看下這裡 深入分析FragmentManager管理機制(一)


推薦閱讀:

安卓手機顯示屏壞了怎麼備份資料?
什麼叫沉浸式狀態欄?
android會有類似蘋果降頻讓手機變卡的行為嗎?
react native 適配安卓有難度么?
如何看待MIUI開始默認取消內存顯示?

TAG:Java | Android | UI開發 |