Android FragmentManager 和 Fragment Result API

Posted

技术标签:

【中文标题】Android FragmentManager 和 Fragment Result API【英文标题】:Android FragmentManager and Fragment Result API 【发布时间】:2021-04-09 09:47:26 【问题描述】:

使用新的 Fragment Result API 从其他 2 个 Fragment 获取结果的 Fragment F 怎么可能:A,B 从 A 但不是从 B 获取结果,因为 B 有不同的父 FragmentManager(我没有知道为什么) ?怎么可能是那样的? 2 个片段以相同的方式调用,但它们最终具有相同的 Activity 但不同的 FragmentManager ?函数调用如下:

//这不起作用。设置结果后不调用监听器

private fun navigateToItemLocation() 

        setFragmentResultListener(REQUEST_LOCATION_KEY)  s: String, bundle: Bundle ->

            val locationId = bundle.getParcelable<ParcelUuid>(LOCATION_ID)!!.uuid
            viewModel.viewModelScope.launch(Dispatchers.IO) 
                val location = LocationRepository().get(locationId)!!
                changeItemLocation(location)
            
        


        val action = ItemRegistrationPagerHolderDirections.actionNavItemRegistrationPagerToNavStockLocationSelection()
        findNavController().navigate(action)
    

//这工作正常:

private fun navigateToItemDetails(item: Item2) 

        setFragmentResultListener(SELECTED_ITEM_KEY)  s: String, bundle: Bundle ->

            val propertySetId = bundle.getParcelable<ParcelUuid>(SELECTED_ITEM_SET_ID)!!.uuid
            clearFragmentResultListener(SELECTED_ITEM_KEY)

            viewModel.viewModelScope.launch(Dispatchers.IO) 
                val repository = PropertySetRepository()
                val propertySet = repository.get(propertySetId)!!
                val propertySetInfo = ItemFactory.loadPropertySetInfo(propertySet)

                withContext(Dispatchers.Main)  setPackageCode(null) 
                selectItem(item.item, propertySetInfo, item.description, null)
            
        

        val action = ItemRegistrationPagerHolderDirections.actionNavItemRegistrationToNavStockItemDetails(ParcelUuid(item.item.id), true)
        findNavController().navigate(action)
    

片段 A 和 B 都在单独的动态特征中。我唯一的问题是当调用以下函数时:

fun onSelect() 

        viewModel.pickedLocation.value = (viewModel.selectedLocation as? LocationExt2?)?.location
        val result = bundleOf(Pair(LOCATION_ID, ParcelUuid(viewModel.pickedLocation.value!!.id)))
        setFragmentResult(REQUEST_LOCATION_KEY, result)
        findNavController().popBackStack()
    

setFragmentResult(REQUEST_LOCATION_KEY, 结果)

不产生任何结果,因为 FragmentManager 与调用 Fragment 不同。片段A中的相同方法是:

private fun onSetSelected(id: UUID) 

    propertySets.removeObservers(viewLifecycleOwner)
    adapter.tracker = null
    setFragmentResult(SELECTED_ITEM_KEY, bundleOf(Pair(SELECTED_ITEM_SET_ID, ParcelUuid(id))))
    findNavController().popBackStack()

作为临时解决方法,我用 Activity.supportFragmentManager.setFragmentResultListener 替换了对 Fragment 的 FragmentManager 的调用。它有效,但我仍然不明白为什么片段 A 和 B 的行为不同......

【问题讨论】:

【参考方案1】:

检查您侦听片段结果的片段和设置结果的片段是否在相同片段管理器中。

如果您将Activity.getSupportFragmentManager()Fragment.getParentFragmentManager()Fragment.getChildFragmentManager() 一起使用,则会发生这种情况的常见情况。

【讨论】:

【参考方案2】:

查看这篇博客文章,了解使用 Fragment Result API 的原则和规则,媒体:https://medium.com/@FrederickKlyk/state-of-the-art-communication-between-fragments-and-their-activity-daa1fe4e014d

一个特定的请求键只能注册一个监听器。

如果在同一个 key 上注册了多个监听器,前一个监听器将被最新的监听器替换。

【讨论】:

以上是关于Android FragmentManager 和 Fragment Result API的主要内容,如果未能解决你的问题,请参考以下文章

Android 11(仅限)FragmentManager 崩溃 - FragmentManager 已被销毁

Android FragmentManager 和 Fragment Result API

android.support.v4.app.FragmentManager无法转换为android.app.FragmentManager

Android中FragmentManager进行片段回收的目的是啥?

Android - 通过 FragmentManager 替换片段后,片段返回到它们的第一个状态

android.support.v4.app.FragmentPagerAdapter 不能应用于 android.app.FragmentManager