繁体   English   中英

为什么Android Navigation Component 屏幕不返回上一个Fragment,而是调用了previos Fragment 的onViewCreated 中的一个方法?

[英]Why Android Navigation Component screen not go back to previous Fragment,but a method in onViewCreated of previos Fragment being called?

我有 2 个片段调用CreateRoomFragmentDisplayPhotoFragment ,导航图如下所示:

<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()来处理弹出窗口。

使用操作进行导航时,您可以选择使用操作的popUpTopopUpToInclusive参数从返回堆栈中弹出其他目的地。

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://gist.githubusercontent.com/cdmunoz/ebe5c4104dadc2a461f512ea1ca71495/raw/a17f76754f86a4c0b1a6b43f5c6e6d179535e627/SingleLiveEvent.kt

有关此检查的详细信息:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM