簡體   English   中英

Android 導航組件:如何獲取當前導航圖的id?

[英]Android navigation component: How to get the current navigation graph's id?

我正在使用嵌套導航圖 scope 並在一組片段中共享我的視圖模型。

我還有一個 BaseFragment class,它獲取對所需視圖模型的引用:

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

如果我需要將 viewmodel 的范圍限定為具有該特定 id 的導航圖(或嵌套導航圖),我可以覆蓋屬性viewModelScopeGraphId 理想情況下,我只想設置一個 boolean 標志,如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 )。 有什么我想念的嗎?

我有一個類似的問題(最后是我案例的更多背景),嘗試了一些解決方案,但都沒有成功。

最后,我放棄了,只將圖形 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 ,只需使用 Navigation navGraphViewModels
    private val listenerViewModel: ListenerViewModel by navGraphViewModels(
            R.id.my_graph_a
    )    
  • 從另一個圖/片段我簡單地做:
    private val listenerViewModel: ListenerViewModel by navGraphViewModels(
            R.id.my_graph_b
    )    

稍微解釋一下我的案例的背景:

  • 我有兩個不同的片段,用戶可以在其中單擊國家/地區選擇。
    • 這些 Fragment 中的每一個都位於不同的 Graph 中,因為它們是不同的流。
  • 國家選擇是一個片段,其中從 API 加載支持的國家列表,顯示它,預先選擇任何以前的用戶選擇(也作為 FragmentArgs 給出),用戶可以更改選擇,這意味着返回上一個屏幕, 使用新選擇的值,或者只是回來而不在此處觸發任何內容。
  • 我知道並期待發布https://issuetracker.google.com/issues/79672220 ,但就像今天(2020 年 3 月)一樣,它僅在alpha可用。

您可以嘗試使用圖表的起始目的地進行檢查。

when (navController.graph.startDestinationId) {
    R.id.firstFragmentOfFirstGraph -> { /* First graph */ }
    R.id.firstFragmentOfSecondGraph -> { /* Second graph */}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM