[英]Why Android Navigation Component screen not go back to previous Fragment,but a method in onViewCreated of previos Fragment being called?
我有 2 個片段調用CreateRoomFragment
和DisplayPhotoFragment
,導航圖如下所示:
<navigation>
<fragment
android:id="@+id/createRoomFragment"
android:name="package.room.CreateRoomFragment"
android:label="Create a room"
tools:layout="@layout/fragment_create_room">
<action
android:id="@+id/action_createRoomFragment_to_roomFragment"
app:destination="@id/roomFragment" />
<action
android:id="@+id/action_createRoomFragment_to_displayPhotoFragment"
app:destination="@id/displayPhotoFragment" />
</fragment>
<fragment
android:id="@+id/displayPhotoFragment"
android:name="package.fragment.DisplayPhotoFragment"
android:label="fragment_display_photo"
tools:layout="@layout/fragment_display_photo" >
<argument android:name="bitmap"
app:argType="android.graphics.Bitmap"/>
</fragment>
所以當我想從CreateRoomFragment
移動到DisplayPhotoFragment
,我使用如下方法:
NavDirections action = CreateRoomFragmentDirections.actionCreateRoomFragmentToDisplayPhotoFragment(selectedPhoto);
Navigation.findNavController(view).navigate(action);
這樣做,我可以導航到DisplayPhotoFragment
。
但是,當我按back
了裝置的按鈕,也Back arrow
從工具欄,它不能回去CreateRoomFragment
。
我試過這個,但仍然無法回到上一個片段:
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(),
new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
navController.navigateUp(); //I tried this
navController.popBackStack(R.id.createRoomFragment,false); //and also this
}
});
現在主要問題:
使用上面的代碼,屏幕沒有回到之前的Fragment( CreateRoomFragment
)。它仍然卡在DisplayPhotoFragment
,但同時調用了CreateRoomFragment
onViewCreated
部分的API方法。
這是什么原因造成的? 我該如何解決這個問題?
我有同樣的問題。 對我來說,問題是我使用 LiveData 布爾值來決定何時轉到下一個片段。 當我向后/向上導航時,布爾值仍然為真,因此它會再次自動向前導航。
Android 維護一個返回堆棧,其中包含您訪問過的目的地。 當用戶打開應用程序時,應用程序的第一個目的地被放置在堆棧中。 每次調用navigate()
方法都會將另一個目標放在堆棧頂部。 Tapping Up 或 Back 分別調用NavController.navigateUp()
和NavController.popBackStack()
方法,以從堆棧中移除(或彈出)頂部目標。
NavController.popBackStack()
返回一個布爾值,指示它是否成功彈出回另一個目的地。 返回 false 的最常見情況是您手動彈出圖形的起始目的地。
當該方法返回 false 時, NavController.getCurrentDestination()
返回 null。 您負責導航到新目的地或通過在您的 Activity 上調用finish()
來處理彈出窗口。
使用操作進行導航時,您可以選擇使用操作的popUpTo
和popUpToInclusive
參數從返回堆棧中彈出其他目的地。
class MyFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (true == conditionForCustomAction) {
CustomActionHere()
} else NavHostFragment.findNavController(this@MyFragment).navigateUp();
}
}
requireActivity().onBackPressedDispatcher.addCallback(
this, onBackPressedCallback
)
...
}
使用實時數據處理導航的最佳解決方案是使用 SingleLiveEvent。
你總是可以使用這個類,它是 MutableLiveData 的擴展。
有關此檢查的詳細信息:
https://proandroiddev.com/singleliveevent-to-help-you-work-with-livedata-and-events-5ac519989c70
有一個類似的問題。 我們仍然有多個帶有導航組件的活動。 所以想象一下活動 A -> 活動 B,活動 B 有自己的導航和片段。 當初始片段嘗試彈出返回堆棧時,無處彈出,導航控制器不知道要完成活動。 所以我找到的一個解決方案是做
if (!findNavController().popBackStack()) activity?.finish()
如果導航控制器無法彈出,它將完成活動。
如果您只想觀察事件一次,則可以在MutableLiveData
上使用MutableSharedFlow
。
在您的viewModel
:
private val _events = MutableSharedFlow<Event>()
val events = _events.asSharedFlow() // read-only public view
suspend fun postEvent() {
_events.emit(event) // suspends until subscribers receive it
}
在您的Activity/Fragment
類中:
lifecycleScope.launchWhenStarted {
viewModel.events.collect {
}
}
viewModel.postEvent()
這將防止在返回片段時連續觀察數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.