在导航到目的地时只创建一个Fragment实例(Android)

18

我正在使用导航组件。在导航时,如果在后退堆栈中已存在该片段,则不希望创建其新实例,并弹出前面已存在的那个。

    findNavController().navigate(RequestTransferFragmentDirections.actionRequestTransferFragmentToBlankFragment())

期待找到解决方案。

谢谢。


请添加更多关于您问题的细节。添加一些代码以展示您已编程的内容或添加一张有用的图片。这样,您就更有可能得到问题的答案。 - Daan Seuntjens
我已经添加了代码。如果不够,请告诉我应该添加什么代码。 - Aleksadnre Bibilashvili
你好,你找到了添加一个片段实例的方法吗? - Alan Deep
1
你好,我在主活动中重写了onNavigationItemSelected(item: MenuItem): Boolean函数,并使用了navOptions。代码如下: val navBuilder = NavOptions.Builder() val navOptions = navBuilder.setPopUpTo(item.itemId, true).build() - Aleksadnre Bibilashvili
4个回答

8

我也遇到了同样的问题,但之前的解决方案对我不起作用,尽管它们应该可以解决这个问题。顺便说一句,谢谢!:)

这个方法对我有用,适应于你的代码:

findNavController().navigate(
    RequestTransferFragmentDirections.actionRequestTransferFragmentToBlankFragment()),
    NavOptions.Builder().setLaunchSingleTop(true).build()
)

我在navigate()文档中看到,我们可以通过传递选项,因此通过传递NavOptions.Builder().setLaunchSingleTop(true).build()将创建这个片段的单个实例。


5

我在这个模式中实现了仅一种片段类型的请求:

在navigation_graph.xml中,我声明了一个弹出操作指向片段目标。

<action
    android:id="@+id/home_action"
    app:destination="@id/my_dest"
    app:popUpTo="@id/my_dest"
    app:popUpToInclusive="true" />

<fragment
    android:id="@+id/my_dest"
    android:name="com.project.android.fragments.MyFragment"
    android:label=""
    tools:layout="@layout/my_fragment_layout" />

在代码中我调用了该操作

navController.navigate(R.id.home_action)

它对我有用。谢谢。这个解释帮助我更好地理解这些操作选项:https://dev59.com/sVMI5IYBdhLWcg3wj8KF#70143987 - André Luiz Reis

5

我在这里回答,因为我也有同样的问题。以下是对我有效的解决方案。最终,我使用了导航控制器,并在存在后退栈目标时将其弹出,如果不存在,则正常导航到它。

具体实现如下:

if ( ! nav.popBackStack(R.id.action_profile, false)) {
    nav.navigate(R.id.action_profile)
}

如果传入的目标不在backstack中,nav.popBackStack(R.id.action_profile, false)将返回false;否则,它将弹出到该目标并返回true。布尔值用于同时弹出目标碎片。
来自文档:
/**
     * Attempts to pop the controller's back stack back to a specific destination.
     *
     * @param destinationId The topmost destination to retain
     * @param inclusive Whether the given destination should also be popped.
     *
     * @return true if the stack was popped at least once and the user has been navigated to
     * another destination, false otherwise
     */
    public boolean popBackStack(@IdRes int destinationId, boolean inclusive) {
        boolean popped = popBackStackInternal(destinationId, inclusive);
        // Only return true if the pop succeeded and we've dispatched
        // the change to a new destination
        return popped && dispatchOnDestinationChanged();
    }


2
你可以像这样做:
bottomNavigation.setupWithNavController(navController)
bottomNavigation.setOnNavigationItemSelectedListener {
    if (it.itemId == R.id.navigation_home) {
        navController.popBackStack(R.id.navigation_home, false)
        true
    }
    else
        NavigationUI.onNavDestinationSelected(it , navController)
}

enter image description here

上述代码中,每当用户点击底部导航视图中的“主页”(R.id.navigation_home)项时,应用程序将使用popBackStack()返回到现有实例的“主页”目标。
如果用户选择底部导航中的另一个目标,则应用程序将使用NavigationUI.onNavDestinationSelected()导航到该目标。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接