欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

自定義Navigator切換fragment - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 技術(shù)分享 >

自定義Navigator切換fragment

發(fā)表時(shí)間:2020-10-18

發(fā)布人:葵宇科技

瀏覽次數(shù):123

使用場(chǎng)景:

使用Navigation完成fragment間的跳轉(zhuǎn)操作。


問(wèn)題描述:

Navigation 實(shí)現(xiàn) fragment 間的跳轉(zhuǎn)用的是replace()方法,此方法會(huì)移除原來(lái)的fragment,再添加新的fragment,所以回到上一個(gè)fragment時(shí)就需要重新走一遍生命周期流程,重新加載數(shù)據(jù)。


解決方案:

分析 NavController類(lèi) 中的navigate 源碼

private void navigate(@NonNull NavDestination node, @Nullable Bundle args,
            @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
        ...
        Navigator<NavDestination> navigator = mNavigatorProvider.getNavigator(
                node.getNavigatorName());  根據(jù)節(jié)點(diǎn)名稱(chēng)生成不同的navigator
        Bundle finalArgs = node.addInDefaultArgs(args);
        NavDestination newDest = navigator.navigate(node, finalArgs,
                navOptions, navigatorExtras);  調(diào)用navigator 中的 navigate方法
       ...
    }

getNavigator 源碼如下

private final HashMap<String, Navigator<? extends NavDestination>> mNavigators =
        new HashMap<>();

public <T extends Navigator<?>> T getNavigator(@NonNull String name) {
    if (!validateName(name)) {
        throw new IllegalArgumentException("navigator name cannot be an empty string");
    }

    Navigator<? extends NavDestination> navigator = mNavigators.get(name); // 根據(jù)傳入的node獲取不同的navigator
    if (navigator == null) {
        throw new IllegalStateException("Could not find Navigator with name \"" + name
                + "\". You must call NavController.addNavigator() for each navigation type.");
    }
    return (T) navigator;
}

因此,想要調(diào)用自定義navigate()方法就需要 自定義一個(gè)Navigator類(lèi),同時(shí)改變fragment節(jié)點(diǎn)名稱(chēng),將fragment節(jié)點(diǎn)名稱(chēng)與Navigator類(lèi)作為key,value 添加到 HashMap類(lèi)型的mNavigators中。

自定義Navigator

@Navigator.Name("custom_fragment")  // 節(jié)點(diǎn)名稱(chēng)定義為custom_fragment,作為 mNavigatorProvider 變量的 key
class CustomNavigator(  //作為 mNavigatorProvider 變量的 value
    private val context: Context,
    private val manager: FragmentManager,
    private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {

    override fun navigate(  // 重寫(xiě) navigate 方法
        destination: Destination,
        args: Bundle?,
        navOptions: NavOptions?,
        navigatorExtras: Navigator.Extras?
    ): NavDestination? {
        val tag = destination.id.toString() // 跳轉(zhuǎn)目的地
        val transaction = manager.beginTransaction() // 開(kāi)啟fragment事務(wù)

        val currentFragment = manager.primaryNavigationFragment // navigation 頂層fragment
        if (currentFragment != null) {
            transaction.hide(currentFragment)   // 隱藏當(dāng)前fragment
        }

        var fragment = manager.findFragmentByTag(tag)   // 找到目的地fragment
        if (fragment == null) { // fragment未被初始化
            val className = destination.className
            fragment = manager.fragmentFactory.instantiate(context.classLoader, className) // 實(shí)例化 fragment
            transaction.add(containerId, fragment, tag) // 將碎片添加到容器中
        } else { // fragment 已經(jīng)初始化過(guò)了
            transaction.show(fragment) // 顯示fragment
        }

        transaction.setPrimaryNavigationFragment(fragment) //將fragment 設(shè)置為頂層fragment
        transaction.setReorderingAllowed(true)
        transaction.commitNow() // 提交事務(wù)

        return destination // 返回目的地,用于監(jiān)聽(tīng)
    }
}

修改節(jié)點(diǎn)名稱(chēng)

因?yàn)楣?jié)點(diǎn)名稱(chēng)定義為custom_fragment,所以修改為<custom_fragment>

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_nav"
    app:startDestination="@id/home_dest"
    tools:ignore="UnusedNavigation">

    <custom_fragment
        android:id="@+id/home_dest"
        android:name="com.cl.androidstudy.ui.home.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />
    <custom_fragment
        android:id="@+id/system_dest"
        android:name="com.cl.navicationtest.SystemFragment"
        android:label="fragment_system"
        tools:layout="@layout/fragment_system" />
    <custom_fragment
        android:id="@+id/square_dest"
        android:name="com.cl.navicationtest.SquareFragment"
        android:label="fragment_square"
        tools:layout="@layout/fragment_square" />
    <custom_fragment
        android:id="@+id/me_dest"
        android:name="com.cl.androidstudy.ui.me.MeFragment"
        android:label="fragment_me"
        tools:layout="@layout/fragment_me" />
</navigation>

邏輯代碼

val navController = Navigation.findNavController(this, R.id.fragment) // 創(chuàng)建navController
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment)!!
val navigator = CustomNavigator(
    this,
    navHostFragment.childFragmentManager,
    R.id.fragment
)// 生成自定義Navigator對(duì)象
navController.navigatorProvider.addNavigator("custom_fragment", navigator) // 添加 key, value
navController.setGraph(R.navigation.my_nav)  // 要在 CustomNavigator 類(lèi)被加載之后添加graph,不然找不到 custom_fragment節(jié)點(diǎn)

參考博客: https://juejin.im/post/6844903896104747022#heading-2

相關(guān)案例查看更多