10

Android Jetpack (2.2.0-alpha01) のナビゲーション コンポーネントを使用しています。

独自の子 nav グラフを備えた、メインの NavHostFragment 内にネストされた子 NavHostFragment を使用したいと考えています。コンテキストについては、次の画像をご覧ください。

ここに画像の説明を入力

子ナビゲーション ホストは、MainNavHost のスタックの先頭にあるフラグメント内で次のように定義されます。

<fragment
    android:id="@+id/childNavHostFragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="false"
    app:navGraph="@navigation/child_graph" />

CHILD Nav Host Fragment の先頭にあるフラグメント内で、次のコードを使用して、R.navigation.child_graph をスコープとする ViewModel を取得しようとしています。

private val childGraphScopedViewModel: ChildGraphScopedViewModel by navGraphViewModels(R.navigation.child_graph) {
    viewModelFactory
}

childGraphScopedViewModel にアクセスすると、クラッシュして次のエラー メッセージが表示されます。

java.lang.IllegalArgumentException: No NavGraph with ID 2131689472 is on the NavController's back stack.

怠惰な init 呼び出しby navGraphViewModel()は、mainGraph 内の navgraph を探していると思います。

子 navHostFragment スコープの ViewModel にアクセスするにはどうすればよいですか? お時間をいただきありがとうございます。

4

3 に答える 3

5

子のviewModelStoreを提供することでそれを行うことができますNavController

override fun onViewCreated(
     view: View, 
     savedInstanceState: Bundle?
) {
    super.onViewCreated(view, savedInstanceState)

    val childHostFragment = childFragmentManager
          .findFragmentById(R.id.childNavHostFragment) as NavHostFragment

    val childNavController = childHostFragment.navController

    val childViewModel: ChildGraphScopedViewModel = ViewModelProvider(
         childNavController.getViewModelStoreOwner(R.navigation.child_graph)
    ).get(ChildGraphScopedViewModel::class.java)
}

簡単にするためにKotlin Extensionを書きました

inline fun <reified T: ViewModel> NavController.viewModel(@NavigationRes navGraphId: Int): T {
    val storeOwner = getViewModelStoreOwner(navGraphId)
    return ViewModelProvider(storeOwner)[T::class.java]
}

使用法

val viewModel = findNavController().viewModel(R.navigation.nav)
于 2019-09-04T10:01:14.717 に答える
3

何らかの理由で、ナビゲーション グラフを作成し、includeそれをメインのナビゲーション グラフ内にネストするために使用することがうまくいきませんでした。おそらくバグです。

ナビゲーション グラフ内でグループ化する必要があるすべてのフラグメントを選択し、right-click->move to nested graph->new graph

これで、選択したフラグメントが、次のようにメインのナビゲーション グラフ内のネストされたグラフに移動します。

<navigation app:startDestination="@id/homeFragment" ...>
    <fragment android:id="@+id/homeFragment" .../>
    <fragment android:id="@+id/productListFragment" .../>
    <fragment android:id="@+id/productFragment" .../>
    <fragment android:id="@+id/bargainFragment" .../>

    <navigation 
        android:id="@+id/checkout_graph" 
        app:startDestination="@id/cartFragment">

        <fragment android:id="@+id/orderSummaryFragment".../>
        <fragment android:id="@+id/addressFragment" .../>
        <fragment android:id="@+id/paymentFragment" .../>
        <fragment android:id="@+id/cartFragment" .../>

    </navigation>

</navigation>

ここで、ViewModel を初期化するときにフラグメント内でこれを行います

val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph)

ビューモデル ファクトリを渡す必要がある場合 (ビューモデルを注入するためである可能性があります)、次のように実行できます。

val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph) { viewModelFactory }
于 2020-05-21T07:53:01.123 に答える