由于大部分和/或所有我的Android开发知识都来自Google关于使用Kotlin开发android应用程序的Udacity的课程,因此我遇到了一个问题,即条件导航仅触发一次,而任何其他触发条件都将其锁定在循环。
希望这里有足够的信息来避免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值为假, 它将正确地将我导航到登录屏幕并返回。如果是第二次 该应用程序将锁定。
编辑:
要求的方法
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")
}