(譯)Fragment 1.2 新特性

本文譯自AndroidDevSummit 2019: What's new in Android Fragments,介紹了Fragment 1.2版本中引入的FragmentContainerView和FragmentFactory的使用。

本文首發(fā):http://yuweiguocn.github.io/

《過零丁洋》
辛苦遭逢起一經(jīng),干戈寥落四周星。
山河破碎風(fēng)飄絮,身世浮沉雨打萍。
惶恐灘頭說惶恐,零丁洋里嘆零丁。
人生自古誰無死?留取丹心照汗青。
-宋代,文天祥

新特性

在2019 AndroidDevSummit上我注意到的一件事情是發(fā)布了androidx.fragment:1.2.0-rc01。這個(gè)是當(dāng)前release版本的候選,這個(gè)版本包含一些更容易處理fragment的新的API。

在本文中,我們來學(xué)習(xí)一下這個(gè)版本中新添加的兩個(gè)API。FragmentContainerView是一個(gè)應(yīng)該被用于fragment的宿主的新View,它替換了通常使用的FrameLayout。還有一個(gè)FragmentFactory用于自定義fragment如何被創(chuàng)建。

FragmentContainerView vs FrameLayout

在activity中使用FrameLayout作為fragment的宿主是一個(gè)很常見的模板。在Android社區(qū)中已經(jīng)這么做了很多年但這馬上將會改變。androidx團(tuán)隊(duì)引入了名為FragmentContainerView的View處理這個(gè)事情。

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

你所需要做的就是使用FragmentContainerView替換FrameLayout并且一切都會開箱即用,對于你處理的fragment transactions什么都不需要修改。譯者注:FragmentContainerView繼承自FrameLayout,但只允許添加fragment view。

它帶來的好處是改進(jìn)了對fragment z-ordering的處理。這個(gè)是他們使用是例子,這意味著兩個(gè)fragment之前的退出和進(jìn)入過渡不會互相重疊。使用FragmentContainerView將先開啟退出動畫然后才是進(jìn)入動畫。

如果你問這個(gè)能否代替<fragment>標(biāo)簽?答案是可以的。你需要做的是添加android:name="your_class_name",它會使用FragmentTransaction構(gòu)建顯示你的fragment。這意味著稍候你可以使用fragment transactions替換它。

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:name="com.company.FragmentClass"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

FragmentFactory

對于創(chuàng)建一個(gè)Fragment最常見的建議是讓你的fragment保留一個(gè)無參的構(gòu)造方法。直到現(xiàn)在,Android框架需要這個(gè)無參構(gòu)造方法實(shí)例化你的fragment。FragmentFactory的到來改變了這一現(xiàn)狀。它可以讓你控制怎樣構(gòu)建fragment,這意味著你可以在fragment中使用構(gòu)造函數(shù)依賴注入。

你需要做的是繼承FragmentFactory并提供你的自定義實(shí)現(xiàn),然后告訴fragment manager構(gòu)建fragment時(shí)使用這個(gè)factory。

// Your custom fragment factory
class MyFragmentFactory (
    private val exampleService: ExampleService
) : FragmentFactory() {

    override fun instantiate(classLoader: ClassLoader, className: String): Fragment { ... }

}

// Your Activity
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var fragmentFactory: MyFragmentFactory

    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory = fragmentFactory
        super.onCreate(savedInstanceState)
        ...
    }
}

還有就是Android社區(qū)習(xí)慣創(chuàng)建fragment的實(shí)例然后傳遞它到fragment transaction。

supportFragmentManager
            .beginTransaction()
            .replace(R.id.fragment_container, SecondFragment())
            .commit()

在這個(gè)新版本中,FragmentTransaction有一些新的重載允許你傳遞Class<Fragment>,然后它會被傳遞到FragmentFactory創(chuàng)建fragment的實(shí)例。因此上面例子的代碼會變得像這樣。

supportFragmentManager.beginTransaction()
                .replace(R.id.fragment_container, SecondFragment::class.java, args = null)
                .commit()

使用FragmentScenario測試fragment

我們都有依賴Dagger獲取依賴的fragment。現(xiàn)在使用FragmentFactory可以很容易使用構(gòu)造函數(shù)注入替換Dagger注入。這也讓測試這些fragment變得容易,不用擔(dān)心通過dagger注入mocks。

androidx.fragment:fragment-testing也進(jìn)行了更新允許你在測試時(shí)提供factory構(gòu)建fragment。這意味著你可以在fragment中使用假的factory通過構(gòu)造函數(shù)注入假依賴。這個(gè)是例子:

val scenario = launchFragmentInContainer<FirstFragment>(factory = MockFactory())
        // Your test action
        scenario.onFragment { fragment ->
            // Your test assertions

        }

總結(jié)

新發(fā)布的androidx.fragment對于簡化fragment的使用邁出了很大一步。至少對我來說易于配置和測試是很友好的改變,我也希望你找到對你有用的。

對于本版本中包含的所有更改請參考官方發(fā)版文檔。

如果你想測試這些在build.gradle添加依賴:

  def fragment_version = "1.2.0-rc01"
  implementation "androidx.fragment:fragment-ktx:$fragment_version"
  implementation "androidx.fragment:fragment-testing:$fragment_version"
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容