Странная ошибка в навигации между фрагментами
Все приветствую! Загадочная ошибка, над которой бьюсь уже несколько дней и не могу найти ответа. Логика такая, что при нажатии на item в recyclerView открывается ViewFragment в котором находится ViewPager2 с двумя фрагментами на борту. В первом фрагменте имеется простая форма ввода данных. При нажатии на кнопку сохранить в родительском фрагменте, информация сохраняется в базу данных Room и отправляет пользователя к изначальному фрагменту с recycler view. Проблема заключается в том, что при первом прогоне такого цикла все работает хорошо, но если повторить действия то приложение крашится вот с такой трассировкой:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.gumbuddy, PID: 30688
java.lang.IllegalArgumentException: Navigation action/destination com.example.gumbuddy:id/action_exerciseSettingFragment_to_addTrainingFragment cannot be found from the current destination Destination(com.example.gumbuddy:id/addTrainingFragment) label=AddTrainingFragment class=com.example.gumbuddy.ui.fragments.workout.addNewTraining.AddTrainingFragment
at androidx.navigation.NavController.navigate(NavController.kt:1540)
at androidx.navigation.NavController.navigate(NavController.kt:1472)
at androidx.navigation.NavController.navigate(NavController.kt:1930)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment.saveExerciseSettingLinear(ExerciseSettingLinearFragment.kt:99)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment.access$saveExerciseSettingLinear(ExerciseSettingLinearFragment.kt:22)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment$onViewCreated$1.invoke(ExerciseSettingLinearFragment.kt:43)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment$onViewCreated$1.invoke(ExerciseSettingLinearFragment.kt:41)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment.onViewCreated$lambda$0(ExerciseSettingLinearFragment.kt:41)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment.$r8$lambda$73BdcS5f30Wd3-a9i3qoyC7j3Z4(Unknown Source:0)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingLinearFragment$$ExternalSyntheticLambda0.onChanged(Unknown Source:2)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at com.example.gumbuddy.ui.viewmodels.MainViewModel.updateDataFragment(MainViewModel.kt:57)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingFragment.init$lambda$3$lambda$1(ExerciseSettingFragment.kt:71)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingFragment.$r8$lambda$iRN9QPNav_1-f_Az-ywsOL_H78w(Unknown Source:0)
at com.example.gumbuddy.ui.fragments.workout.addNewTraining.ExerciseSettingFragment$$ExternalSyntheticLambda2.onClick(Unknown Source:4)
at android.view.View.performClick(View.java:7503)
at android.view.View.performClickInternal(View.java:7480)
at android.view.View.access$3600(View.java:813)
at android.view.View$PerformClick.run(View.java:28445)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7977)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:603)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:948)
I/Process: Sending signal. PID: 30688 SIG: 9
Disconnected from the target VM, address: 'localhost:40701', transport: 'socket'
Код адаптера RecyclerView изначальный фрагмент:
val adapter = WorkoutAdapter {
viewModel.updateCurrentExercise(it)
val action = AddTrainingFragmentDirections.actionAddTrainingFragmentToExerciseSettingFragment()
this.findNavController().navigate(action)
}
binding.rcViewNewTraining.adapter = adapter
adapter.submitList(viewModel.addExerciseToTheTrainingList())
Код функции инициализации ViewPager2 во втором фрагменте:
private fun init() = with(binding) {
val adapter = VpAdapter(activity as FragmentActivity, fList)
vp2.adapter = adapter
TabLayoutMediator(tabLayout, vp2) {
tab, pos -> tab.text = tList[pos]
}.attach()
binding.btnSaveTraining.setOnClickListener {
if (vp2.currentItem == 0) {
viewModel.updateDataFragment(KEY_LINEAR)
} else {
viewModel.updateDataFragment(KEY_PYRAMID)
}
}
binding.btnCleanTraining.setOnClickListener {
viewModel.updateDataFragment(KEY_CLEAR)
}
}
Код функции сохранения данных на третьем фрагменте:
private fun saveExerciseSettingLinear(view: View) {
val idExercise = viewModel.exercise.value?.id
val approach = binding.edApproach.text
val repeat = binding.edRepeat.text
val weight = binding.edWeight.text
val comment = binding.edComment.text
if (approach.isEmpty() || repeat.isEmpty() || weight.isEmpty()) {
Snackbar.make(
view,
"Заполните все необходимые поля",
Snackbar.LENGTH_SHORT
).show()
} else {
val settingLinear = ExerciseSettingLinear(idExercise, approach.toString().toInt(),
repeat.toString().toInt(), weight.toString().toDouble(), comment.toString())
val action = ExerciseSettingFragmentDirections.actionExerciseSettingFragmentToAddTrainingFragment()
if (comment.isEmpty()) {
settingLinear.comment = ""
viewModel.insertExerciseSettingLinear(settingLinear)
lifecycleScope.launch {
viewModel.saveIdExerciseSettingLinear()
}
findNavController().navigate(action)
} else {
viewModel.insertExerciseSettingLinear(settingLinear)
lifecycleScope.launch {
viewModel.saveIdExerciseSettingLinear()
}
findNavController().navigate(action)
}
}
}
Код сохранения данных во viewModel:
//Сохранение настроек упражнения линейного типа в базу данных Room
fun insertExerciseSettingLinear(exerciseSettingLinear: ExerciseSettingLinear) = viewModelScope.launch {
mainRepository.insertExerciseSettingLinear(exerciseSettingLinear)
}
//Получить все настройки по ID записи
suspend fun getIdExerciseSettingLinear(id: Int): ExerciseSettingLinear = withContext(Dispatchers.IO) {
mainRepository.getIdExerciseSettingLinear(id)
}
//Получить ID последней записи в базе
private fun updateLastIdSettingLinear() = mainRepository.getLastIdExerciseSettingLinear()
Репозиторий:
class MainRepository @Inject constructor(
private val trainingDao: TrainingDao,
private val linearDao: LinearDao,
private val pyramidDao: PyramidDao
) {
suspend fun insertTraining(training: Training) = trainingDao.insertTraining(training)
suspend fun insertExerciseSettingLinear(exerciseSettingLinear: ExerciseSettingLinear) = linearDao.insertExerciseSettingLinear(exerciseSettingLinear)
suspend fun insertExerciseSettingPyramid(exerciseSettingPyramid: ExerciseSettingPyramid) = pyramidDao.insertExerciseSettingPyramid(exerciseSettingPyramid)
fun getIdExerciseSettingLinear(id: Int): ExerciseSettingLinear = linearDao.getIdExerciseSettingLinear(id)
fun getLastIdExerciseSettingLinear(): Int = linearDao.getLastIdExerciseSettingLinear()
}
Dao interface:
@Dao
interface LinearDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertExerciseSettingLinear(exerciseSettingLinear: ExerciseSettingLinear)
@Query("SELECT * FROM exercise_setting_linear_table WHERE id = :id")
fun getIdExerciseSettingLinear(id: Int?): ExerciseSettingLinear
@Query("SELECT MAX(id) FROM exercise_setting_linear_table")
fun getLastIdExerciseSettingLinear(): Int
}