Сбой приложения при переходе к фрагменту

#android #kotlin #navigation

Вопрос:

Я использую 3 фрагмента с 1 активностью для функций профиля пользователя. Я использую навигацию для перехода к фрагментам: Навигационный график

Проблема в том, что когда я перехожу из фрагмента профиля в фрагмент editProfileFragment, изменяю данные пользователя, а затем возвращаюсь к фрагменту профиля с помощью действия навигации, я не могу снова перейти к фрагменту editProfileFragment из фрагмента профиля. Я получил эту ошибку:

 Navigation action/destination xxx:id/action_profileFragment_to_editProfileFragment cannot be found from the current destination Destination(xxx:id/editProfileFragment)
 

Я пытаюсь использовать архитектуру MVVM, поэтому моя навигация выглядит следующим образом — во фрагменте я наблюдаю живые данные:

 navController = Navigation.findNavController(view)
        viewModel.navigateTo.observe(viewLifecycleOwner, EventObserver {
            navController.navigate(it)
        })
 

Модель просмотра «Навигация»:

 private val _navigateTo = MutableLiveData<Event<Int>>()
    val navigateTo: LiveData<Event<Int>> = _navigateTo
 

и методы навигации:

 fun goBackToProfile(){
        _navigateTo.value = Event(R.id.action_editProfileFragment_to_profileFragment)
    }

fun editProfileButtonClick() {
        _navigateTo.value = Event(R.id.action_profileFragment_to_editProfileFragment)
    }
 

Я также использую класс оболочки событий Хосе Альсеррека:

 open class Event<out T>(private val content: T) {

    var hasBeenHandled = false
        private set // Allow external read but not write

    /**
     * Returns the content and prevents its use again.
     */

    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    fun peekContent(): T = content
}

class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
    override fun onChanged(event: Event<T>?) {
        event?.getContentIfNotHandled()?.let {
            onEventUnhandledContent(it)
        }
    }
}
 

Я не знаю, возникает ли ошибка из-за оболочки события или я делаю что-то не так с навигацией. Я буду признателен за любые советы.

ИЗМЕНИТЬ: navigation.xml:

 <?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/main_nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@ id/homeFragment"
        android:name="xxx.mainPackage.views.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />
    <fragment
        android:id="@ id/profileFragment"
        android:name="xxx.mainPackage.views.ProfileFragment"
        android:label="fragment_profile"
        tools:layout="@layout/fragment_profile" >
        <action
            android:id="@ id/action_profileFragment_to_editProfileFragment"
            app:destination="@id/editProfileFragment" />
    </fragment>
    <fragment
        android:id="@ id/editProfileFragment"
        android:name="xxx.mainPackage.views.EditProfileFragment"
        android:label="fragment_edit_profile"
        tools:layout="@layout/fragment_edit_profile" >
        <action
            android:id="@ id/action_editProfileFragment_to_chooseImageFragment"
            app:destination="@id/chooseImageFragment" />
        <action
            android:id="@ id/action_editProfileFragment_to_profileFragment"
            app:destination="@id/profileFragment" />
    </fragment>
    <fragment
        android:id="@ id/chooseImageFragment"
        android:name="xxx.mainPackage.views.ChooseImageFragment"
        android:label="ChooseImageFragment" >
        <action
            android:id="@ id/action_chooseImageFragment_to_editProfileFragment"
            app:destination="@id/editProfileFragment" />
    </fragment>
</navigation>
 

Комментарии:

1. Можете ли вы поделиться своим кодом navigation.xml ?

2. Код в отредактированном вопросе

Ответ №1:

Мне кажется, что ты идешь не в ту сторону.

Во-первых

Вы движетесь от ProfileFragment туда EditProfileFragment . Затем вы переходите от EditProfileFragment действия к ProfileFragment действию, чей идентификатор R.id.action_profileFragment_to_editProfileFragment .

Это действие , которое, как я вижу, вы определяете из Фрагмента ProfileFragment , а не EditFragment .

Убедитесь, что ваши navigateTo данные в EditProfileFragment идентификаторе триггера R.id.action_editProfileFragment_to_profileFragment указаны, когда вы хотите открыть ProfileFragment EditProfileFragment .

Во-вторых

Когда вы вернетесь EditProfileFragment , не звоните navController.navigate() , так как это сохранит ваш текущий фрагмент в фоновом режиме и переместит ваш целевой фрагмент в фоновый режим. Если вы хотите вернуться, не сохраняя свой текущий фрагмент в резерве, позвоните navController.popBackStack() .

Комментарии:

1. Я вижу проблему, теперь она работает, спасибо, что уделили мне время

Ответ №2:

Ошибка очень ясна, нет action_profileFragment_to_editProfileFragment определенного включения editProfileFragment . если вы посмотрите на свой xml-файл навигации, вы увидите, что action_profileFragment_to_editProfileFragment он определен для ProfileFragment .

Но вы пытаетесь использовать это действие навигации , из EditProfileFragment -за которого возникает ошибка. поэтому либо обновите навигацию, чтобы включить это действие EditProfileFragment , либо используйте какое-то действие, для которого оно уже определено EditProfileFragment .