【问题标题】:Android navigation component: How to get the current navigation graph's id?Android导航组件:如何获取当前导航图的id?
【发布时间】:2020-01-11 07:21:59
【问题描述】:

我正在使用嵌套导航图,以便在一组片段中划分和共享我的视图模型。

我还有一个 BaseFragment 类,它获取对所需视图模型的引用:

fun provideViewModel() : VM {
        return if(viewModelScopeGraphId != null) {
            ViewModelProvider(findNavController().getViewModelStoreOwner(viewModelScopeGraphId!!)).get(viewModelClass)
        } else {
            ViewModelProvider(this).get(viewModelClass)
        }
     }

如果我需要将视图模型限定为具有该特定 ID 的导航图(或嵌套导航图),我可以覆盖属性 viewModelScopeGraphId。 理想情况下,我只想设置一个布尔标志,如 useScopedViewModel 并获取当前导航图的 id,例如:

fun provideViewModel() : VM {
        return if(useScopedViewModel) {
            ViewModelProvider(findNavController().getViewModelStoreOwner(getCurrentNavGraphId())).get(viewModelClass)
        } else {
            ViewModelProvider(this).get(viewModelClass)
        }
     }

我曾尝试使用navController.graph.id 获取当前图形ID,但我从那里获得的ID 似乎与我的资源ID 不匹配(例如R.id.nav_graph)。有什么我遗漏的吗?

【问题讨论】:

    标签: android android-architecture-components android-architecture-navigation


    【解决方案1】:

    我有一个类似的问题(最后我的案例的更多背景),尝试了一些解决方案,但都没有成功。

    最后我放弃了,只给了graph id作为Fragment的参数。

    因为它可以帮助您实现自己的解决方案,所以我的解决方案如下所示:

    • 必须创建这个扩展,因为原来的navGraphViewModels 只接受@IdRes navGraphId: Int,我想延迟加载参数等。(到目前为止,我还简化了从参数中删除factoryProducer我不会将它用于我们的解决方案。
    inline fun <reified VM : ViewModel> Fragment.navGraphViewModels(
            noinline graphIdProducer: () -> Int
    ): Lazy<VM> {
        val backStackEntry by lazy {
            findNavController().getBackStackEntry(graphIdProducer())
        }
        val storeProducer: () -> ViewModelStore = {
            backStackEntry.viewModelStore
        }
        return createViewModelLazy(VM::class, storeProducer, {
            backStackEntry.defaultViewModelProviderFactory
        })
    }
    
    • 在我想要使用它的片段中,我使用navArgs 恢复参数,并使用上面的扩展名恢复ViewModel
        private val listenerViewModel: ListenerViewModel by navGraphViewModels {
            navArgs.graphId
        }
    
        private val navArgs: MyFragmentArgs by navArgs()
    
    • 对于需要“收听”ViewModel 的任何人,只需使用导航 navGraphViewModels 进行加载即可:
        private val listenerViewModel: ListenerViewModel by navGraphViewModels(
                R.id.my_graph_a
        )    
    
    • 从另一个图表/片段我简单地做:
        private val listenerViewModel: ListenerViewModel by navGraphViewModels(
                R.id.my_graph_b
        )    
    

    解释一下我的案例的背景:

    • 我有两个不同的片段,用户可以在其中单击国家选择。
      • 这些片段中的每一个都位于不同的图表中,因为它们是不同的流。
    • 国家/地区选择是一个片段,从 API 加载支持的国家/地区列表,显示它,预先选择任何以前的用户选择(也作为 FragmentArgs 给出),用户可以更改选择,这意味着返回上一个屏幕,使用新选择的值,或者只是返回此处不触发任何内容。
    • 我知道并期待 https://issuetracker.google.com/issues/79672220 的发布,但就像今天(2020 年 3 月)一样,它仅在 alpha 中可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 2020-12-15
      相关资源
      最近更新 更多