[英]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.