如何在非主线程中可靠设置LiveData值?
LiveData非主线程更新UI的问题与解决方案
非主线程完成操作后,若要通过LiveData通知Fragment更新UI,通常会用postValue()替代setValue(),但存在部分发布的值无法被主线程的Fragment观察到的问题——比如在一个工作路径地标展示场景中,使用postValue()时就出现了部分预期地标未显示的情况。
解决方法一:协程切换主线程设置值
让运行在Dispatchers.IO的工作协程通过withContext切换到主线程执行值设置操作,可确保通知被主线程的观察者接收到。以下是带注解的扩展函数实现:
companion object { @OptIn(ExperimentalStdlibApi::class) suspend fun WorkingDepth.resetDepthOnMain() { if (currentCoroutineContext()[CoroutineDispatcher].toString() == "Dispatchers.Main") { resetDepth() } else { coroutineScope { withContext(Dispatchers.Main) { // 该方式可确保主线程收到通知 // 若在非主线程用postValue,无法保证观察者能收到通知 resetDepth() } } } } }
如果不想使用@OptIn(ExperimentalStdlibApi::class)注解,也可以默认将所有调度器视为非Dispatchers.Main,直接切换到主线程执行,额外开销可忽略。
另一种解决思路:捕获异常后重试
由于在非主线程直接调用setValue()会抛出异常,也可以通过捕获该异常,再切换到主线程重试设置值。
疑问
既然postValue()存在通知丢失的问题,且非主线程直接调用setValue()会报错,那LiveData为何不内置“主线程安全设置值”的功能,反而要依赖postValue()这种“寄望生效”的方式?
内容的提问来源于stack exchange,提问作者Mike Hanafey
相关产品推荐
相关产品推荐

