问题描述
我的目的是将动态要素模块中的片段显示为ViewPager2的根片段。
我设法用BottomNavigationView
,here来签出,但是当BottomNavigationView位于片段中时,NavigationExtension 导致内存泄漏,我可能会尝试重新为BottomNavigationView编写另一个扩展以防止内存泄漏,但这可能会花费很多时间,并且还希望对动态功能模块中的片段使用ViewPager2
。
我还可以在应用模块中使用一个空的代理片段,并让该片段导航到动态功能模块中的片段,但这将意味着为每个页面创建不必要的片段。
我作为动态功能模块片段并作为BottomNavigationView的根使用的是
创建了一个片段,该片段扩展了DynamicNavHostFragment
以动态创建一个片段。 NavHostFragment.create(navigationId)的问题是它没有返回类型T extends 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()的键和值与NavHostFragment源代码中使用的相同。
并更改了NavigationExtensions.kt中的gainNavHostFragment()函数
private fun obtainNavHostFragment(
fragmentManager: FragmentManager,fragmentTag: String,navGraphId: Int,containerId: Int
): NavHostFragment {
// If the Nav Host fragment exists,return it
val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
existingFragment?.let { return it }
// Otherwise,create it and return it.
val navHostFragment = BaseDynamicNavHostFragment.createDynamicNavHostFragment(navGraphId)
fragmentManager.beginTransaction()
.add(containerId,navHostFragment,fragmentTag)
.commitNow()
return navHostFragment
}
Changed NavHostFragment.create()
至BaseDynamicNavHostFragment.createDynamicNavHostFragment(navGraphId)
在应用程序模块导航文件夹中创建的代理Navigation_graphs使用带有<include-dynamic>
的动态功能模块图
<?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"
android:id="@+id/nav_graph_dashboard_start"
app:startDestination="@id/nav_graph_dashboard">
<!-- Dashboard dynamic feature module -->
<include-dynamic
android:id="@+id/nav_graph_dashboard"
android:name="com.smarttoolfactory.dashboard"
app:graphResName="nav_graph_dashboard"
app:moduleName="dashboard">
</include-dynamic>
</navigation>
和动态功能模块中
<?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>
与BottomNavigationView
一起使用
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
)
这对于BottomNavigationView
很好用,并且对于ViewPager2
实现相同的事情
我在下面创建了FragmentAdapter
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
有一个sample您可以尝试,它现在在开发分支中名为MainFragmentWithViewPager的片段中。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)