我正在制作一款支持不同设备方向的应用程序.导航由Android Jetpack的导航系统执行.应用程序的横向主屏幕如下所示.它是列表包装器片段(它是NavHostFragment,被添加到fragment标记中的活动布局中),包装器包括列表片段(fragment)和细节片段(FrameLayout).纵向方向类似(包装和列表在其中,详细信息可通过导航访问).

App main screen

我的问题是,在我改变设备方向后,我遇到了异常

JAVAlang.IllegalStateException:没有当前导航 node

First version of my layout with mocked data worked fine, the error appears after I add ROOM to my app, new order and update order fragments. It is a pity, I cannot localize source of error more exact.

List wrapper code

class OrderListWrapperFragment : RxFragment() {

    private val disposable = CompositeDisposable()

    var selectedOrderId: Long = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val bundle = savedInstanceState ?: arguments
        bundle?.let {
            selectedOrderId = it.getLong(EXTRA_ORDER_ID)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(R.layout.orders__list_wrapper, container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        initializeToolbar(toolbar, getString(R.string.orders_title), false)

        newOrderButton
            .clicks()
            .subscribe {
                findNavController()
                    .navigate(R.id.action_orderListWrapperFragment_to_orderNewFragment)
            }
            .addTo(disposable)

        childFragmentManager.registerFragmentLifecycleCallbacks(callback, false)
    }

    override fun onDestroyView() {
        super.onDestroyView()

        childFragmentManager.unregisterFragmentLifecycleCallbacks(callback)

        disposable.clear()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        outState.putLong(EXTRA_ORDER_ID, selectedOrderId)
    }

    private val callback = object : FragmentManager.FragmentLifecycleCallbacks() {

        private val disposable = CompositeDisposable()

        override fun onFragmentResumed(fm: FragmentManager, fragment: Fragment) {
            super.onFragmentResumed(fm, fragment)

            if (fragment is OrderListFragment) {
                fragment
                    .selectedItemIdChanges
                    .subscribeBy(onNext = {
                        selectedOrderId = it
                        if (orderDetailsContainer != null) {
                            childFragmentManager.commit {
                                replace(
                                    R.id.orderDetailsContainer,
                                    OrderDetailsFragment.newInstance(it)
                                )
                            }
                        } else {
                            findNavController()
                                .navigate(
                                    R.id.action_orderListWrapperFragment_to_orderDetailsFragment,
                                    bundleOf(EXTRA_ORDER_ID to it)
                                )
                            selectedOrderId = 0
                        }
                    },
                        onError = {
                            Log.d("detailView", it.toString())
                        })
                    .addTo(disposable)

                val orderId = selectedOrderId
                if (orderId != 0L) {
                    if (orderDetailsContainer != null) {
                        childFragmentManager.commit {
                            replace(
                                R.id.orderDetailsContainer,
                                OrderDetailsFragment.newInstance(orderId)
                            )
                        }
                    } else {
                        findNavController()
                            .navigate(//exception throws here
                                R.id.action_orderListWrapperFragment_to_orderDetailsFragment,
                                bundleOf(EXTRA_ORDER_ID to orderId)
                            )
                        selectedOrderId = 0
                    }
                }
            }
        }

        override fun onFragmentPaused(fm: FragmentManager, fragment: Fragment) {
            super.onFragmentPaused(fm, fragment)

            if (fragment is OrderListFragment) {
                disposable.clear()
            }
        }
    }

    companion object {
        private const val EXTRA_ORDER_ID = "EXTRA_ORDER_ID"
    }
}

My navigation graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/orderListWrapperFragment">

    <fragment
        android:id="@+id/orderListWrapperFragment"
        android:name="com.mtgshipping.app.orders.orderList.OrderListWrapperFragment"
        android:label="OrderListWrapperFragment"
        tools:layout="@layout/orders__list_wrapper">
        <action
            android:id="@+id/action_orderListWrapperFragment_to_orderDetailsFragment"
            app:destination="@id/orderDetailsFragment"/>
        <action
            android:id="@+id/action_orderListWrapperFragment_to_orderNewFragment"
            app:destination="@id/orderNewFragment"/>
        <action
            android:id="@+id/action_orderListWrapperFragment_to_orderUpdateFragment"
            app:destination="@id/orderUpdateFragment"/>
    </fragment>

    <fragment
        android:id="@+id/orderDetailsFragment"
        android:name="com.mtgshipping.app.orders.orderDetails.OrderDetailsFragment"
        android:label="OrderDetailsFragment"
        tools:layout="@layout/orders__order_details">
        <action
            android:id="@+id/action_orderDetailsFragment_to_orderUpdateFragment"
            app:destination="@id/orderUpdateFragment"/>
    </fragment>

    <fragment
        android:id="@+id/orderNewFragment"
        android:name="com.mtgshipping.app.orders.orderNew.OrderNewFragment"
        android:label="OrderNewFragment"
        tools:layout="@layout/orders__order_new">
        <action
            android:id="@+id/action_orderNewFragment_to_orderListWrapperFragment"
            app:destination="@id/orderListWrapperFragment"/>
    </fragment>

    <fragment
        android:id="@+id/orderUpdateFragment"
        android:name="com.mtgshipping.app.orders.orderUpdate.OrderUpdateFragment"
        android:label="OrderUpdateFragment"
        tools:layout="@layout/orders__order_update">
        <action
            android:id="@+id/action_orderUpdateFragment_to_orderListWrapperFragment"
            app:destination="@id/orderListWrapperFragment"/>
    </fragment>
</navigation>

I made some debug in NavController, it showed in line 746 NavDestination currentNode = mBackStack.isEmpty() ? mGraph : mBackStack.getLast().getDestination(); after device rotation mGraph is null, other private fields is also null. Maybe something prevents NavController to initialize properly. I can provide layouts and other code, if it will be need.

推荐答案

多亏了斯拉夫的 comments ,他是对的.我在APP的模块build.gradle中将导航模块更新为2.2.0 navigation_version = '2.2.0'

implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"

完成此操作后,问题不再出现,看起来这是导航中的一个错误.

Kotlin相关问答推荐

如何为集成测试配置Gradle JVM测试套件?

如何在操作系统版本上正确获取Room数据库的路径>;=26 sdk?

为什么使用 return instance ?: synchronized(this) { instance ?: PreferenceParameterState(context) } 时无法获得单例?

使用 Kotlin 的 Springboot 中缺少 ResponseEntity 正文属性

mutableStateOf 和 mutableStateListOf 有什么区别?

如何在 Jetpack Compose 中启动和停止动画

如何在 Spring Boot 3 中为内部类提供运行时提示

Kotlin:使用另一个列表和字母顺序对列表进行排序的有效方法

如何使用成员引用在 Kotlin 中创建属性的分层路径

如何处理基于枚举提前返回的 forEach 循环,Kotlin 中的一条路径除外

如何在 kotlin 中使用带有泛型的密封类

TestContainers PostgreSQLContainer 与 Kotlin 单元测试:Not enough information to infer type variable SELF

jetpack compose 将参数传递给 viewModel

IntelliJ 不会根据 ktlint 的期望对 Kotlin 导入进行排序

如何在调试中修复 ClassNotFoundException: kotlinx.coroutines.debug.AgentPremain?

如何在 Kotlin 中为变量设置监听器

launch 仅从 Kotlin 1.3 开始可用,不能在 Kotlin 1.2 中使用

用Gradle Kotlin DSL构建源jar?

接口中的属性不能有支持字段

无法解决:androidx.lifecycle:lifecycle-extensions-ktx:2.0.0-alpha1