Поскольку большинство и / или все мои знания в области разработки для Android были получены из курса Google по Udacity, посвященного разработке приложений для Android с Kotlin, я столкнулся с проблемой, когда моя условная навигация срабатывает только один раз, и любые дальнейшие триггеры блокируют приложение в петля.
Надеюсь, здесь достаточно информации, чтобы избежать проблемы XY. Это также может быть слишком многословно, так как я пытался вставить резинку в текстовое поле, чтобы увидеть, не заметил ли я каких-либо явных проблем.
Приложение представляет собой отдельное приложение, которое использует компоненты архитектуры Android, привязку данных и библиотеку навигации. Он также использует Android AWS SDK, но я не думаю, что это имеет отношение к проблеме.
Следуя принципам навигации Google, конечный пункт назначения
не экран входа в систему.
Экран входа в систему зависит от состояния входа в систему
от AWSMobileClient верно.
Класс применения
AWSMobileClient инициализируется в приложении расширения класса
AWSMobileClient.getInstance().initialize(applicationContext, object : Callback<UserStateDetails> {
override fun onResult(userStateDetails: UserStateDetails) {
Timber.i("Inside init function onResult: %s", userStateDetails.userState)
}
override fun onError(e: Exception) {
Timber.e(e, "Initialization error.")
}
}
)
Модель главного экрана
Проверяет состояние входа и устанавливает MutableLiveData с этим логическим значением
private var _isSignedIn = MutableLiveData<Boolean>()
val isSignedIn: LiveData<Boolean>
get() = _isSignedIn
init {
startup()
}
private fun startup() {
Timber.i(
"Startup isSignedIn state: %s",
AWSMobileClient.getInstance()?.isSignedIn.toString()
)
_isSignedIn.value = AWSMobileClient.getInstance().isSignedIn
}
fun logout() {
Timber.i("Trying to logout now..")
AWSMobileClient.getInstance().signOut()
_isSignedIn.value = false
}
Фрагмент главного экрана
Timber.i("Viewmodel in oncreate")
val homeScreenViewModel =
ViewModelProviders.of(this)
.get(HomeScreenViewModel::class.java)
binding.homeScreenViewModel = homeScreenViewModel
binding.lifecycleOwner = viewLifecycleOwner
val navController = findNavController()
homeScreenViewModel.isSignedIn.observe(viewLifecycleOwner, Observer { signIn ->
if (signIn) {
Timber.i("ifTrue isSignedIn")
homeScreenViewModel.apiCall()
}
else {
navController.navigate(HomeScreenFragmentDirections.actionHomeScreenFragmentToLoginFragment())
Timber.i("Else isSignedIn")
}
})
Чистая установка приложения
Logcat
2019-07-03 15:30:38.727 I/AWSKeyValueStore: Creating the AWSKeyValueStore with key for sharedPreferences = CognitoIdentityProviderCache
2019-07-03 15:30:38.752 I/ExampleApplication$onCreate: Inside init function onResult: SIGNED_OUT
2019-07-03 15:30:38.759 I/HomeScreenFragment: Viewmodel in oncreate
2019-07-03 15:30:38.759 I/HomeScreenViewModel: Startup isSignedIn state: false
2019-07-03 15:30:38.778 I/HomeScreenFragment$onCreateView: Else isSignedIn
2019-07-03 15:30:39.182 I/HomeScreenFragment: Homescreen fragment onStop
На данный момент приложение находится на экране входа в систему, и все работает как положено.
Он
- Запущен фрагмент рабочего стола
-Проверено мое состояние входа в систему, видит, что я не вошел в систему,
-Навидит меня к экрану входа в систему.
Logcat после входа в систему
2019-07-03 15:33:39.605 I/LoginViewModel$signIn: Sign-in callback state: DONE
2019-07-03 15:33:39.605 I/LoginViewModel$signIn: Sign-in done.
2019-07-03 15:33:39.611 I/HomeScreenFragment: Viewmodel in oncreate
2019-07-03 15:33:39.618 I/HomeScreenViewModel: Startup isSignedIn state: true
2019-07-03 15:33:39.626 I/HomeScreenFragment$onCreateView: ifTrue isSignedIn
2019-07-03 15:33:39.628 I/HomeScreenFragment: Homescreen fragment onResume
2019-07-03 15:33:39.635 I/HomeScreenViewModel: Viewmodel onCleared
2019-07-03 15:33:39.635 I/HomeScreenFragment: Homescreen fragment onDestroy
Я успешно вошел в систему, вернулся на домашний экран, мое состояние входа проверено,
видит, что я вошел в систему, получает данные из API и отображает их в
обзор переработчика.
Я не уверен, почему фрагмент / модель представления очищены / уничтожены. Фрагмент
все еще на экране и может взаимодействовать с ним.
Когда я нажимаю кнопку выхода на фрагменте домашнего экрана, из окна модели вызывается функция выхода из системы
и в этот момент приложение блокируется, и мой logcat - это, повторяется до бесконечности
2019-07-03 15:40:39.756 I/HomeScreenViewModel: Trying to logout now..
2019-07-03 15:40:39.779 I/HomeScreenFragment$onCreateView: Else isSignedIn
2019-07-03 15:40:39.834 I/HomeScreenFragment: Homescreen fragment onPause
2019-07-03 15:40:39.835 I/HomeScreenFragment: Homescreen fragment onStop
2019-07-03 15:40:39.837 I/HomeScreenFragment: Viewmodel in oncreate
2019-07-03 15:40:39.838 I/HomeScreenViewModel: Startup isSignedIn state: false
2019-07-03 15:40:39.840 I/HomeScreenFragment$onCreateView: Else isSignedIn
2019-07-03 15:40:39.840 I/HomeScreenFragment: Homescreen fragment onResume
2019-07-03 15:40:39.840 I/HomeScreenViewModel: Viewmodel onCleared
2019-07-03 15:40:39.841 I/HomeScreenFragment: Homescreen fragment onDestroy
Если я убью приложение и перезапущу его, оно появится на экране входа в систему, как и ожидалось.
Запуск приложения, когда я уже вошел в систему
Если я запускаю приложение и уже вошел в систему, я остаюсь на фрагменте домашнего экрана.
Когда я нажимаю кнопку выхода, я выхожу из системы и перехожу на экран входа в систему.
2019-07-03 15:43:40.417 I/ExampleApplication$onCreate: Inside init function onResult: SIGNED_IN
2019-07-03 15:43:40.438 I/HomeScreenFragment: Viewmodel in oncreate
2019-07-03 15:43:40.447 I/HomeScreenViewModel: Startup isSignedIn state: true
2019-07-03 15:43:40.485 I/HomeScreenFragment$onCreateView: ifTrue isSignedIn
2019-07-03 15:43:40.650 I/HomeScreenFragment: Homescreen fragment onResume
2019-07-03 15:43:40.835 I/OpenGLRenderer: Initialized EGL, version 1.4
2019-07-03 15:43:40.835 W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
2019-07-03 15:43:45.086 I/HomeScreenViewModel: Trying to logout now..
2019-07-03 15:43:45.115 I/HomeScreenFragment$onCreateView: Else isSignedIn
2019-07-03 15:43:45.676 I/HomeScreenFragment: Homescreen fragment onPause
2019-07-03 15:43:45.676 I/HomeScreenFragment: Homescreen fragment onStop
2019-07-03 15:43:45.758 I/art: Do partial code cache collection, code=27KB, data=29KB
2019-07-03 15:43:45.759 I/art: After code cache collection, code=24KB, data=28KB
2019-07-03 15:43:45.759 I/art: Increasing code cache capacity to 128KB
В этот момент я могу войти в систему и вернусь на домашний экран.
Нажатие на кнопку выхода заблокирует приложение, пока оно не будет убито и перезапущено.
Так что мне кажется, что пока наблюдатель впервые видит значение signIn ложным,
он будет правильно перемещать меня к экрану входа и обратно. Если это второй раз, однако,
приложение блокируется.
EDIT:
запрошенные методы
override fun onPause() {
super.onPause()
Timber.i("Homescreen fragment onPause")
}
override fun onStop() {
super.onStop()
Timber.i("Homescreen fragment onStop")
}
override fun onResume() {
super.onResume()
Timber.i("Homescreen fragment onResume")
}
override fun onDestroy() {
super.onDestroy()
Timber.i("Homescreen fragment onDestroy")
}