文章目錄
- 1. FragmentManager簡介
- 2. FragmentManager的擷取
-
- 2.1 從Activity中擷取FragmentManager
- 2.2 從Fragment上擷取FragmentManager
- 3. FragmentTransaction簡介
- 4. FragmentTransaction的擷取
- 5. 二者結合的典型用法
- 6. 擷取某個已添加的Fragment
-
- 6.1 findFragmentById
- 6.2 findFragmentByTag
- 7. 支援多個Fragment背景棧
- 8. 總結
1. FragmentManager簡介
FragmentManager,顧名思義是負責管理Fragment的管理類,可以對Fragment進行添加、移除、替換等操作。并且,Fragment也有和Activity類似的任務棧。Fragment可被添加到棧中,也可以出棧。
2. FragmentManager的擷取
2.1 從Activity中擷取FragmentManager
從前面的章節我們了解到,Fragment是依附在Activity上的子頁面。那麼負責管理這些子頁面的FragmentManager自然可從Activity上擷取了。隻不過這種Activity比較特殊,是一種FragmentActivity。
ApppCompatActivity、FragmentActivity、Activity三者的繼承關系是: ApppCompatActivity繼承自FragmentActivity,FragmentActivity繼承自Activity
是以,FragmentActivity或者是繼承自FragmentActivity的子類(比如,ApppCompatActivity)都可以獲得FragmentManager。擷取方法是:
。從support可以看出,這裡擷取的是具有相容性的Fragment,也就是Android Support或者AndroidX包裡面的Fragment。
getSupportFragmentManager()
- 注意,不要用老舊的
,
android.app.fragment
,已不推薦使用。
getFragmentManager()
2.2 從Fragment上擷取FragmentManager
Fragment除了依附在Activity上,也可以依附在别Fragmet上。這時被依附的Fragment就是父Fragment,依附的Fragment就是子Fragment。
那麼管理子Fragment的FragmentManager自然可以從其父Fragment裡擷取。方法是:
getChildFragmentManager()
。也好了解,管理子Fragment嘛,自然是getChildFragmentManager。
上面是一個Fragment擷取其子Fragment的管理類(
getChildFragmentManager()
),而要想擷取管理自身的管理類,可以通過
getParentFragmentManager()
方法實作。
Fragment與其持有者(Activity或父Fragment),還有FragmentManager的對應關系可用下圖表示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdmVGbfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0DOXVmNw5WY0olMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmLiJDZzEmY4QTZ5QmMyUjZiJWNhRzNygTO5QzYwITZidzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
3. FragmentTransaction簡介
FragmentManager是Fragment的管理者,但它還需要一個助手幫它完成Fragment的add、replace等操作。這個助手就是FragmentTransaction。
對Fragment的添加、替換等操作可能會有多個。比如先移除目前FragmentA,再添加FragmentB,這樣兩個操作通常就被打包一次Transaction,統一送出(commit)。比如下面的代碼:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.remove(fragmentA)
.add(R.id.fragment_container, FragmentB.class,null)
.setReorderingAllowed(true)
.addToBackStack("name") // name can be null
.commit();
- Transaction,是事務的意思,原本是資料庫中的概念。引申到這裡,可了解為把多個操作打包為整體,統一送出。如果其中某個操作失敗了,那麼整個操作全部恢複到操作之前。這樣可以保證操作的完整性。
- 舉個例子,A向B轉賬100元的操作可簡化為以下幾步:1.A的賬戶錢數減100; 2. B的賬戶加100。假如操作1執行完,操作2執行失敗了,那麼整個轉賬操作應該認為是失敗的,應該回退到轉賬之前。這時候“事務”的操作就發揮作用了。根據“事務”的概念,1和2應該是一個整體,2失敗了,那麼所有操作恢複到操作之前。是以,“操作1. A的賬戶錢數減100”,就會回退到之前,即再加100恢複到原數目,進而保證了資料的完整性。
4. FragmentTransaction的擷取
從上面代碼可以看出FragmentTransaction是FragmentManager的助手,自然會通過FragmentManager獲得。如下代碼:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
5. 二者結合的典型用法
了解了FragmentManager以及FragmentTransaction後,我們來看二者結合後常見的操作,比如将一個Fragment添加到某個FragmentContainer上。
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, ExampleFragment.class, null)
.setReorderingAllowed(true)
.addToBackStack("name") // name can be null
.commit();
這裡值得注意的有以下幾點:
- 使用ExampleFragment.class而不是某個ExampleFragment對象,原因上節已經解釋過
- 添加setReorderingAllowed(true),原因仍參見上節
- addToBackStack(“name”),将本次操作整體添加到一個背景棧裡。當使用者點選傳回鍵時,就能依次彈出,當彈到棧為空,時再按傳回鍵,事件就會傳遞到所在Activity,執行其任務棧的回退。
- 如果不加addToBackStack,當你移除一個Fragment後,該Fragment會被銷毀,無法再跳到該Fragment。而加了addToBackStack後,Fragment被移除後,該Fragment隻是切換到了Stop狀态,仍然有機會再跳轉到該Fragment。
6. 擷取某個已添加的Fragment
Fragment被添加後,有兩種方式擷取已添加的Fragment對象。
- findFragmentById
- findFragmentByTag
6.1 findFragmentById
通過被添加到的容器的id擷取,該容器上目前的Fragment執行個體。
代碼舉例如下:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, ExampleFragment.class, null)
.setReorderingAllowed(true)
.addToBackStack(null)
.commit();
ExampleFragment fragment =
(ExampleFragment) fragmentManager.findFragmentById(R.id.fragment_container);
6.2 findFragmentByTag
Fragment添加的時候,可以為其加上一個Tag作為标簽。這樣後面就可以根據該标簽找到它了。
代碼舉例如下:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, ExampleFragment.class, null, "tag")
.setReorderingAllowed(true)
.addToBackStack(null)
.commit();
ExampleFragment fragment = (ExampleFragment) fragmentManager.findFragmentByTag("tag");
7. 支援多個Fragment背景棧
有時我們需要同時操作多個Fragment棧。比如,底部導航菜單+多個Fragment頁面。通過FragmentManager,我們可以暫存某個棧,顯示另一個棧。對應的方法分别是
saveBackStack()
和
restoreBackStack()
。
代碼舉例如下:
首先,将Fragment添加到棧
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, ExampleFragment.class, null)
.setReorderingAllowed(true)
.addToBackStack("replacement")
.commit();
注意,這裡的和
setReorderingAllowed(true)
是必須的。這樣才能使用saveBackStack和restoreBackStack。
addToBackStack
接着,暫存Fragment棧:
然後,恢複Fragment棧:
8. 總結
本章節介紹了FragmentManager與FragmentTransaction的概念和用法,以及如何擷取某個已添加的Fragment,還涉及了對Fragment背景棧的了解。