Je crée une application qui prend en charge différentes orientations d'appareil. La navigation est effectuée par la navigation d'Android Jetpack. L'écran principal de l'application pour l'orientation paysage est présent ci-dessous. C'est un fragment de wrapper de liste (c'est NavHostFragment , il est ajouté à la mise en page de l'activité dans la balise de fragment ), le wrapper comprend un fragment de liste ( fragment ) et un fragment de détails ( FrameLayout ). L'orientation portrait est similaire (wrapper et liste dedans, les détails sont accessibles par la navigation).
Mon problème est qu'après avoir changé l'orientation de l'appareil, j'obtiens une exception
java.lang.IllegalStateException: aucun nœud de navigation actuel
La première version de ma mise en page avec des données simulées a bien fonctionné, l'erreur apparaît après avoir ajouté ROOM à mon application, une nouvelle commande et des fragments de commande de mise à jour. C'est dommage, je ne peux pas localiser la source d'erreur plus précisément.
Code wrapper de liste
<?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>
Mon graphique de navigation
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"
}
}
J'ai fait un débogage dans NavController , il a montré à la ligne 746 NavDestination currentNode = mBackStack.isEmpty() ? mGraph : mBackStack.getLast().getDestination(); après la rotation de l'appareil, mGraph est null , les autres champs privés sont également null . Peut-être que quelque chose empêche NavController de s'initialiser correctement. Je peux fournir des mises en page et d'autres codes, si nécessaire.
4 Réponses :
Grâce au commentaire de Slav, il avait raison. J'ai mis à jour le module de navigation vers 2.2.0 navigation_version = '2.2.0' dans le module build.gradle
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version" implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
Après avoir fait ce problème n'apparaît plus, il semble que c'était un bogue dans la navigation.
cela ne fonctionne pas pour moi :( stackoverflow.com/questions/60807361/...
Selon la page maven mvnrepository.com/artifact/android.arch.navigation/ ... la dernière version est 1.0.0. Comment utilisez-vous la version 2.2.0?
@ IrvingLóp C'est un ancien paquet, j'utilise la version ktx mvnrepository.com/artifact/androidx.navigation/...
Vous pouvez également le réparer comme ça. Dans votre activité d'hôte dans le manifeste en ajoutant cet attribut:
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
Mais le meilleur moyen est de changer vos dépendances pour la navigation à partir de:
implementation "android.arch.navigation:navigation-fragment-ktx:$navigation_version" implementation "android.arch.navigation:navigation-ui-ktx:$navigation_version"
à
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
C'était mon problème, les vieilles dépendances. Je pense que ces dépendances "android.arch" sont dépréciées pour "androidx"
Je suppose que si vous utilisez l'option android.useAndroidX=true dans votre version, vous avez besoin de androidx.navigation au lieu de android.arch.navigation .
Le passage de "android.arch" à "androidx" a résolu mon problème, merci beaucoup
Oui, cela a été utile! J'ai essayé de mettre à jour vers 2.2.0 comme suggéré dans la réponse ci-dessus, mais j'ai également dû passer d'Android.arch à Androix. Je suis en train de trouver quelques codelabs google qui doivent être mis à jour!
Le problème pour moi était la version de la dépendance du cycle de vie
lifecycle_version = '2.1.0'
la version '2.2.0' cause le problème, je suis retourné à utiliser '2.1.0'
"androidx.lifecycle:lifecycle-extensions:$lifecycle_version
Aucune de ces solutions n'a résolu mon problème.
Je l'ai corrigé en incluant mon graphique imbriqué dans le graphique principal.
J'ai un nav_main qui inclut un nav_sub_1 .
nav_sub_1 comprend également un autre sous-graphe, nav_sub_2
Quand j'ai essayé de démarrer mon activité en mettant nav_sub_2 , la IllegalStateException est survenue
java.lang.IllegalStateException: aucun nœud de navigation actuel
Mais cela ne se produirait pas en définissant nav_main ou nav_sub_1 .
Mon graphique principal nav_main ressemble à ceci:
<navigation
<fragment...>
<include app:graph="@navigation/nav_sub_1
<include app:graph="@navigation/nav_sub_2
<navigation/>
et nav_sub_1 :
<navigation
<fragment...>
<include app:graph="@navigation/nav_sub_2
<navigation/>
J'ai inclus nav_sub_2 dans nav_main et le problème a été résolu!
<navigation
<fragment...>
<include app:graph="@navigation/nav_sub_1
<navigation/>
J'ai corrigé la navigation en mettant à jour le composant de navigation vers la version 2.2.1. Consultez cette réponse: stackoverflow.com/a/58738512/4568679