Android 动态功能模块片段作为ViewPager2 FragmentStateAdapter的片段

Android 动态功能模块片段作为ViewPager2 FragmentStateAdapter的片段,android,android-fragments,android-architecture-navigation,android-viewpager2,dynamic-feature-module,Android,Android Fragments,Android Architecture Navigation,Android Viewpager2,Dynamic Feature Module,我的目标是将动态功能模块中的片段显示为ViewPager2的根片段 我用BottomNavigationView成功地做到了这一点,您可以签出,但是NavigationExtension会导致内存泄漏当BottomNavigationView在片段中时,我可能会尝试为BottomNavigationView重新编写另一个扩展以防止内存泄漏,但这可能需要很多时间,并且还希望将ViewPager2与来自动态功能模块的片段一起使用 我还可以在app模块中使用一个代理空片段,并让该片段导航到dynami

我的目标是将动态功能模块中的片段显示为ViewPager2的根片段

我用
BottomNavigationView
成功地做到了这一点,您可以签出,但是NavigationExtension会导致内存泄漏当BottomNavigationView在片段中时,我可能会尝试为BottomNavigationView重新编写另一个扩展以防止内存泄漏,但这可能需要很多时间,并且还希望将
ViewPager2
与来自动态功能模块的片段一起使用

我还可以在app模块中使用一个代理空片段,并让该片段导航到dynamicfeaturemodule中的片段,但这意味着为每个页面创建不必要的片段

我使用动态功能模块片段作为BottomNavigationView的根所做的工作如下

创建了扩展
DynamicNavHostFragment
以动态创建的片段。NavHostFragment.create(navigationId)的问题在于它没有返回类型
T extensed NavHostFragment
,或者我找不到这样做的方法

/**
 * [DynamicNavHostFragment] creator class which
 * uses [BaseDynamicNavHostFragment.createDynamicNavHostFragment] function with navigation graph
 * parameter
 */
class BaseDynamicNavHostFragment : DynamicNavHostFragment() {

    private val navControllerViewModel by activityViewModels<NavControllerViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
//    override fun onCreate(savedInstanceState: Bundle?) {
//        super.onCreate(savedInstanceState)
//        val navResId = arguments?.get(KEY_GRAPH_ID) as Int
//        val startDestinationArgs = arguments?.get(KEY_START_DESTINATION_ARGS) as? Bundle
//
//        findNavController().setGraph(navResId, startDestinationArgs)
//    }

    override fun onResume() {
        super.onResume()
        // Set this navController as ViewModel's navController
        navControllerViewModel.currentNavController.value = Event(navController)
    }

    override fun onDestroyView() {
        navControllerViewModel.currentNavController.value = Event(null)
        super.onDestroyView()
    }

    companion object {

        private const val KEY_GRAPH_ID = "android-support-nav:fragment:graphId"
        private const val KEY_START_DESTINATION_ARGS =
            "android-support-nav:fragment:startDestinationArgs"

        /**
         * Create a new NavHostFragment instance with an inflated [NavGraph] resource.
         *
         * @param graphResId resource id of the navigation graph to inflate
         * @param startDestinationArgs arguments to send to the start destination of the graph
         * @return a new NavHostFragment instance
         */

        @JvmStatic
        fun createDynamicNavHostFragment(
            @NavigationRes graphResId: Int,
            startDestinationArgs: Bundle? = null
        ): BaseDynamicNavHostFragment {

            if (graphResId == 0) throw NavigationException("Navigation graph id cannot be 0")

            val bundle: Bundle = Bundle().apply {
                putInt(KEY_GRAPH_ID, graphResId)

                if (startDestinationArgs != null) {
                    putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs)
                }
            }

            return BaseDynamicNavHostFragment().apply {
                arguments = bundle
            }
        }
    }
}
将NavHostFragment.create()
更改为
BaseDynamicNavHostFragment.createDynamicNavHostFragment(navGraphId)

应用程序内模块导航文件夹创建了使用动态功能模块图的代理导航图

这适用于
BottomNavigationView
,也适用于
ViewPager2

我在下面创建了碎片适配器

class DynamicFragmentStateAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    NavigableFragmentStateAdapter(fragmentManager, lifecycle) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when (position) {

            // Dashboard nav graph
            0 ->
                BaseDynamicNavHostFragment
                    .createDynamicNavHostFragment(R.navigation.nav_graph_dashboard_start)

            // Notification nav graph
            1 ->
                BaseNavHostFragment
                    .createNavHostFragment(R.navigation.nav_graph_notification_start)

            // Account nav graph
            else ->
                BaseNavHostFragment
                    .createNavHostFragment(R.navigation.nav_graph_account_start)
        }
    }
}
我还使用fragmentManager.replace()进行了签出。如果可以使用片段实例化进行导航,则没有问题,但是使用上面的FragmentStateAdapter,我会得到错误

java.lang.IllegalArgumentException: Must use non-zero containerViewId
我一直在努力解决这个问题,但还没有找到解决办法

有一个你可以尝试的,它现在在开发分支中,在名为MainFragmentWithViewPager的片段中

<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph_dashboard"
    app:moduleName="dashboard"
    app:startDestination="@id/dashboardFragment">

    <fragment
        android:id="@+id/dashboardFragment"
        android:name="com.smarttoolfactory.dashboard.DashboardFragment"
        android:label="Dashboard Fragment"
        tools:layout="@layout/fragment_dashboard" />

</navigation>
val navGraphIds = listOf(
    R.navigation.nav_graph_home,
    R.navigation.nav_graph_dashboard_start,
    R.navigation.nav_graph_notification_start,
    R.navigation.nav_graph_account_start
)

// Setup the bottom navigation view with a list of navigation graphs
val controller = bottomNavigationView.setupWithNavController(
    navGraphIds = navGraphIds,
    fragmentManager = childFragmentManager,
    containerId = R.id.nav_host_container,
    intent = requireActivity().intent
)
class DynamicFragmentStateAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    NavigableFragmentStateAdapter(fragmentManager, lifecycle) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when (position) {

            // Dashboard nav graph
            0 ->
                BaseDynamicNavHostFragment
                    .createDynamicNavHostFragment(R.navigation.nav_graph_dashboard_start)

            // Notification nav graph
            1 ->
                BaseNavHostFragment
                    .createNavHostFragment(R.navigation.nav_graph_notification_start)

            // Account nav graph
            else ->
                BaseNavHostFragment
                    .createNavHostFragment(R.navigation.nav_graph_account_start)
        }
    }
}
java.lang.IllegalArgumentException: Must use non-zero containerViewId