在Kotlin中实现多线程数据刷新的完整方案如下:
一、基础线程刷新方案
-
使用Handler消息机制
在子线程执行耗时任务后,通过
Handler
发送消息到主线程更新UI:// 主线程定义Handler private val handler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when (msg.what) { 1 -> textView.text = msg.obj.toString() } } } // 子线程发送消息 thread { val data = fetchData() // 耗时操作 val msg = Message.obtain().apply { what = 1 obj = data } handler.sendMessage(msg) }
-
runOnUiThread简化操作
在Activity中直接切换至主线程更新UI:
thread { val result = processData() runOnUiThread { textView.text = result } }
二、协程与Flow方案(推荐)
-
协程异步刷新
使用协程切换线程上下文,避免直接操作线程:
viewModelScope.launch(Dispatchers.IO) { val data = repository.loadData() withContext(Dispatchers.Main) { textView.text = data } }
-
Flow周期性自动刷新
通过
flow
实现定时数据刷新:fun tickerFlow(period: Duration) = flow { while (true) { emit(Unit) delay(period) } } // 在ViewModel中触发 viewModelScope.launch { tickerFlow(Duration.seconds(5)) .collectLatest { _ -> val newData = fetchData() _uiState.value = UiState.Success(newData) } }
三、LiveData集成方案
-
结合LiveData自动更新
在ViewModel中通过LiveData
驱动UI刷新:javaclass MyViewModel : ViewModel() { private val _data = MutableLiveData<String>() val data: LiveData<String> = _data fun refresh() { viewModelScope.launch(Dispatchers.IO) { val result = fetchData() _data.postValue(result) } } } // Activity中观察 viewModel.data.observe(this) { textView.text = it }
四、注意事项
- 线程安全 :禁止在子线程直接操作UI控件(如
TextView.setText()
),必须切回主线程 - 资源释放 :在
onDestroy()
中取消协程或清空Handler消息队列,避免内存泄漏 - 性能优化 :高频刷新建议使用
Flow
或LiveData
,避免频繁创建线程
优先推荐协程+Flow/LiveData组合方案,传统Handler方案适用于低版本兼容场景