android - 如何将协程范围限定为片段,以便在片段离开屏幕或被销毁时自动取消?
问题描述
我有这个片段,它只是在检索数据时用作启动屏幕。问题在于,在配置更改或 Fragment 离开屏幕(用户导航出应用程序)时,它会在从 IO Coroutine 块返回并尝试在 Main Coroutine 块中执行导航时崩溃。
这是代码:
注意:viewModel.repository.initData()
如果数据不存在或过时,则进行 Retrofit 调用并将响应持久保存到 Room 数据库。
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)
}
}
}
}
}
推荐阅读
- sql-server - SSMS 批量插入 = 错误 + 是哪一行?
- composer-php - Composer 在一台计算机上非常慢,在其他计算机上没有问题
- python - Numpy 根据 XYZ 获取最大值
- spring - 在 JHipster 中实现文件附件
- php - Firebird pdf blob 通过 PHP 保存为 pdf 文件
- python - 在 python 中使用 lambda 和 regex 对列表进行排序
- python-3.x - Pandas read_excel() 将具有空白值的日期列解析为 NaT
- kerberos - 如何以管理员或 root 身份更新其他用户的 kerbors 票?
- c - 基于两个可能的结构的未知空指针的访问类型标志?
- android - 通过反射找不到Editor类的属性