【问题标题】:How to prevent recreation of Fragments while navigating back and forth?如何防止在来回导航时重新创建片段?
【发布时间】:2019-09-29 09:10:24
【问题描述】:

我有一组片段在活动中导航。当我调用 findFragmentByTag() 时,片段 onCreateView() 和 onViewCreated() 被再次调用并且数据被重置为正常。如何防止fragment的重新创建?

【问题讨论】:

  • 没有足够的信息来回答你的问题,添加代码!!

标签: android android-fragments


【解决方案1】:

您可以查看android示例中的高级导航代码

fun BottomNavigationView.setupWithNavController(
navGraphIds: List<Int>,
fragmentManager: FragmentManager,
containerId: Int,
intent: Intent): LiveData<NavController> {

// Map of tags
val graphIdToTagMap = SparseArray<String>()
// Result. Mutable live data with the selected controlled
val selectedNavController = MutableLiveData<NavController>()

var firstFragmentGraphId = 0

// First create a NavHostFragment for each NavGraph ID
navGraphIds.forEachIndexed { index, navGraphId ->
    val fragmentTag = getFragmentTag(index)

    // Find or create the Navigation host fragment
    val navHostFragment = obtainNavHostFragment(
        fragmentManager,
        fragmentTag,
        navGraphId,
        containerId
    )

    // Obtain its id
    val graphId = navHostFragment.navController.graph.id

    if (index == 0) {
        firstFragmentGraphId = graphId
    }

    // Save to the map
    graphIdToTagMap[graphId] = fragmentTag

    // Attach or detach nav host fragment depending on whether it's the selected item.
    if (this.selectedItemId == graphId) {
        // Update livedata with the selected graph
        selectedNavController.value = navHostFragment.navController
        attachNavHostFragment(fragmentManager, navHostFragment, index == 0)
    } else {
        detachNavHostFragment(fragmentManager, navHostFragment)
    }
}

// Now connect selecting an item with swapping Fragments
var selectedItemTag = graphIdToTagMap[this.selectedItemId]
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
var isOnFirstFragment = selectedItemTag == firstFragmentTag

// When a navigation item is selected
setOnNavigationItemSelectedListener { item ->
    // Don't do anything if the state is state has already been saved.
    if (fragmentManager.isStateSaved) {
        false
    } else {
        val newlySelectedItemTag = graphIdToTagMap[item.itemId]
        if (selectedItemTag != newlySelectedItemTag) {
            // Pop everything above the first fragment (the "fixed start destination")
            fragmentManager.popBackStack(firstFragmentTag,
                FragmentManager.POP_BACK_STACK_INCLUSIVE)
            val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
                as NavHostFragment

            // Exclude the first fragment tag because it's always in the back stack.
            if (firstFragmentTag != newlySelectedItemTag) {
                // Commit a transaction that cleans the back stack and adds the first fragment
                // to it, creating the fixed started destination.
                fragmentManager.beginTransaction()
                    .attach(selectedFragment)
                    .setPrimaryNavigationFragment(selectedFragment)
                    .apply {
                        // Detach all other Fragments
                        graphIdToTagMap.forEach { _, fragmentTagIter ->
                            if (fragmentTagIter != newlySelectedItemTag) {
                                detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
                            }
                        }
                    }
                    .addToBackStack(firstFragmentTag)
                    .setCustomAnimations(
                        R.anim.nav_default_enter_anim,
                        R.anim.nav_default_exit_anim,
                        R.anim.nav_default_pop_enter_anim,
                        R.anim.nav_default_pop_exit_anim)
                    .setReorderingAllowed(true)
                    .commit()
            }
            selectedItemTag = newlySelectedItemTag
            isOnFirstFragment = selectedItemTag == firstFragmentTag
            selectedNavController.value = selectedFragment.navController
            true
        } else {
            false
        }
    }
}

// Optional: on item reselected, pop back stack to the destination of the graph
setupItemReselected(graphIdToTagMap, fragmentManager)

// Handle deep link
setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)

// Finally, ensure that we update our BottomNavigationView when the back stack changes
fragmentManager.addOnBackStackChangedListener {
    if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) {
        this.selectedItemId = firstFragmentGraphId
    }

    // Reset the graph if the currentDestination is not valid (happens when the back
    // stack is popped after using the back button).
    selectedNavController.value?.let { controller ->
        if (controller.currentDestination == null) {
            controller.navigate(controller.graph.id)
        }
    }
}
return selectedNavController

}

这个示例代码你可以在这里找到完整的代码

https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample

【讨论】:

  • 有没有办法在java中得到这个?
  • 这与 java 调用类名并添加 .它会像单身,它会正常工作
猜你喜欢
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多