Android 如何将一个协同程序定义为一个片段,以便在片段离开屏幕或被销毁时自动取消?
我有这个片段,它只是在检索数据时作为一个启动屏幕。问题是,在配置更改时,或者如果片段在屏幕外(用户导航出应用程序),当它从IO协同程序块返回并尝试在主协同程序块中执行导航时,它会崩溃 代码如下: 注意:Android 如何将一个协同程序定义为一个片段,以便在片段离开屏幕或被销毁时自动取消?,android,kotlin,kotlin-coroutines,android-jetpack-navigation,Android,Kotlin,Kotlin Coroutines,Android Jetpack Navigation,我有这个片段,它只是在检索数据时作为一个启动屏幕。问题是,在配置更改时,或者如果片段在屏幕外(用户导航出应用程序),当它从IO协同程序块返回并尝试在主协同程序块中执行导航时,它会崩溃 代码如下: 注意:viewModel.repository.initData()进行改装调用,并在数据不存在或过时时将响应持久化到房间数据库 class LoadingFragment : Fragment() { private lateinit var viewModel: LoadingViewMo
viewModel.repository.initData()
进行改装调用,并在数据不存在或过时时将响应持久化到房间数据库
class LoadingFragment : Fragment() {
private lateinit var viewModel: LoadingViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_loading, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(LoadingViewModel::class.java)
CoroutineScope(Dispatchers.IO).launch {
// Small delay so the user can actually see the splash screen
// for a moment as feedback of an attempt to retrieve data.
delay(250)
try {
viewModel.repository.initData()
CoroutineScope(Dispatchers.Main).launch {
findNavController().navigate(R.id.action_loadingFragment_to_mainFragment)
}
} catch (e: IOException) {
findNavController().navigate(R.id.action_loadingFragment_to_errorFragment)
}
}
}
}
此外,我还需要只在检索数据之后进行导航,但数据检索必须在IO线程上完成,而导航必须在主线程上完成
我一直在阅读有关确定协同程序范围的内容,但我仍然不清楚/不确定它是如何工作的,以及如何正确设置它。我能够通过实现如下内容来修复它:
class LoadingFragment : Fragment() {
private lateinit var viewModel: LoadingViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_loading, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(LoadingViewModel::class.java)
lifecycleScope.launch {
withContext(Dispatchers.IO) {
// Small delay so the user can actually see the splash screen
// for a moment as feedback of an attempt to retrieve data.
delay(250)
try {
viewModel.initData()
withContext(Dispatchers.Main) {
findNavController().navigate(R.id.action_loadingFragment_to_mainFragment)
}
} catch (e: IOException) {
findNavController().navigate(R.id.action_loadingFragment_to_errorFragment)
}
}
}
}
}
我可以通过实现如下内容来修复它:
class LoadingFragment : Fragment() {
private lateinit var viewModel: LoadingViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_loading, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(LoadingViewModel::class.java)
lifecycleScope.launch {
withContext(Dispatchers.IO) {
// Small delay so the user can actually see the splash screen
// for a moment as feedback of an attempt to retrieve data.
delay(250)
try {
viewModel.initData()
withContext(Dispatchers.Main) {
findNavController().navigate(R.id.action_loadingFragment_to_mainFragment)
}
} catch (e: IOException) {
findNavController().navigate(R.id.action_loadingFragment_to_errorFragment)
}
}
}
}
}
您不必自己设置,只需使用
viewModelScope.launch在LoadingViewModel
内的viewModelScope
中运行任务即可{
。@EpicPandaForce我已经尝试过了,但无法让它与导航同步执行。这意味着我只想在数据初始化后进行导航。如果没有多个不同的协同程序,可以只使用已经限定到片段生命范围的程序,lifecycleScope
viewModel.repository、 initData()
应该是一个挂起函数,可以正确处理后台工作并更新主线程上的实时数据。因此,根本没有理由在片段本身中与调度程序发生冲突。您可能甚至不需要存储库,我也不知道为什么有人想将它们强行塞进他们的项目中。您想要Vie吗wModelScope,可能是LiveData
或不是建立在完全不相关的抽象之上的东西,而不是使用。您不必自己设置它,只需在LoadingViewModel
内的viewModelScope
中运行任务,使用viewModelScope.launch{
。@EpicPandaForce我已经尝试过了,但无法让它与导航同步执行。这意味着我只想在数据初始化后进行导航。如果没有多个不同的协同程序,可以只使用已经限定到片段生命范围的程序,lifecycleScope
viewModel.repository、 initData()
应该是一个挂起函数,可以正确处理后台工作并更新主线程上的实时数据。因此,根本没有理由在片段本身中与调度程序发生冲突。您可能甚至不需要存储库,我也不知道为什么有人想将它们强行塞进他们的项目中。您想要Vie吗wModelScope,可能是LiveData
,或者不是建立在完全无关的抽象之上的东西,而是使用