簡體   English   中英

使用 Android 導航將數據傳回前一個片段

[英]Pass data back to previous fragment using Android Navigation

我已經開始使用 Android 架構組件(導航和安全參數、視圖模型)以及 Koin 庫。

目前,我在兩個片段之間傳遞 arguments 時遇到問題 - 我需要將字符串值從片段 A 傳遞到片段 B,在片段 B 中修改此值並將其傳回片段 A。

我找到了一種可能的解決方案來解決我的問題——共享視圖模型。 不幸的是,這種方法有一個問題,因為我可以在屏幕之間傳遞和修改值,但是當片段 A 導航到另一個目的地時,共享視圖 model 中的值仍然被存儲並且沒有被清除。

Android Navigation 中的片段之間傳遞和修改數據是否有任何不同的解決方案? 我想避免手動清除這個值(當片段 A 被銷毀時)。

Android 剛剛為此發布了一個解決方案; 在目標導航 2.3.0-alpha02之間傳遞數據,基本上,在片段 A 中,您觀察變量的變化,而在片段 B 中,您在執行popBackStack()之前更改該值。

片段A:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController();
// We use a String here, but any type that can be put in a Bundle is supported
navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(
    viewLifecycleOwner) { result ->
    // Do something with the result.
  }
}

片段B:

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)
navController.popBackStack()

您可以使用片段結果 API

片段 A -> 片段 B

在片段 A 中:

binding.buttonGo.setOnClickListener {
   setFragmentResultListener(ADD_LOCATION) { key, bundle ->
       clearFragmentResultListener(requestKey = ADD_LOCATION)
       val selectedLocationModel =
           bundle.getParcelable<LocationModel>(SELECTED_LOCATION_MODEL)
       this.selectedLocationModel = selectedLocationModel
   }
   navToFragmentB()
}

在片段 B 中:

setFragmentResult(
    ADD_LOCATION,
    bundleOf(SELECTED_LOCATION_MODEL to selectedLocationModel)
)
goBack()

在創建新的之前不要忘記調用clearFragmentResultListener()

目前,我在兩個片段之間傳遞參數時遇到問題 - 我需要將字符串值從片段 A 傳遞到片段 B,在片段 B 中修改此值並將其傳遞回片段 A。

理論上的解決方案實際上是將兩個片段放在一個共享的<navigation標簽中,然后將 ViewModel 范圍限定為導航標簽的 ID,這樣您現在就可以在兩個屏幕之間共享 ViewModel。

為了使其可靠,最好將 Navigation 標記的 NavBackStackEntry 用作 ViewModelStoreOwner 和 SavedStateRegistryOwner,並創建一個 AbstractSavedStateViewModelFactory,它將使用 ViewModelProvider 創建 ViewModel,同時還為您提供 SavedStateHandle。

您可以使用此 SavedStateHandle 將結果從 FragmentB 傳送到 FragmentA,與共享的 ViewModel(范圍限定為共享的 NavGraph)相關聯。

你可以試試這個解決方案

<fragment
    android:id="@+id/a"
    android:name="...">

    <argument
        android:name="text"
        app:argType="string" />

    <action
        android:id="@+id/navigate_to_b"
        app:destination="@id/b" />

</fragment>

<fragment
    android:id="@+id/b"
    android:name="...">

    <argument
        android:name="text"
        app:argType="string" />

    <action
        android:id="@+id/return_to_a_with_arguments"
        app:destination="@id/a"
        app:launchSingleTop="true"
        app:popUpTo="@id/b"
        app:popUpToInclusive="true" />

</fragment>

和導航片段

NavHostFragment.findNavController(this).navigate(BFragmentDirections.returnToAWithArguments(text))

ianhanniballake 的評論幫我解決了一個類似的問題

1) 使用 action_A_to_B 和 SafeArgs 將字符串從片段 A 傳遞到片段 B。

2) popBackStack 移除 Fragment B。

navController.popBackStack(R.id.AFragment, false);

或者

navController.popBackStack();

3)然后使用action_B_to_A將修改后的數據從B傳遞到A。

編輯。

在這里你有一些另一種解決方案

暫無
暫無

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

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