MVP+Interactors架构下指定线程流程的优雅实现方案咨询
优雅解决线程指定调度的方案(无冗余包装代码)
嘿,这个场景我太熟悉了!之前也烦透了那些到处写的Handler.post或者RunOnUiThread,还要维护AsyncTask的生命周期,简直是代码噪音。刚好有个完美符合你要求的优雅方案,用Kotlin协程就能搞定,完全不用那些繁琐的包装类,也不会阻塞UI线程!
核心思路
利用协程的调度器特性,直接为不同方法指定运行线程,全程无需手动写线程切换的包装代码,逻辑和同步代码一样清晰。
代码实现示例
// 在Activity/Fragment中定义协程作用域,默认绑定UI线程(Main调度器) private val mainScope = MainScope() // 系统触发,本身就在UI线程执行 fun OnClick() { OnRefresh() } // 指定在UI线程执行,直接启动协程调度后续流程 fun OnRefresh() { mainScope.launch { // 切换到IO调度器(Worker线程)执行数据库读取,仅挂起协程不阻塞UI val dbData = withContext(Dispatchers.IO) { ReadDb() } // 协程自动切回UI线程,直接调用SetData更新UI SetData(dbData) } } // 标记为挂起函数,运行在IO线程执行数据库操作 private suspend fun ReadDb(): YourDataModel { // 这里执行实际的数据库读取逻辑 return yourDatabase.yourDao().getTargetData() } // 自动在UI线程执行,更新UI组件 private fun SetData(data: YourDataModel) { yourRecyclerView.adapter?.submitList(data) yourTextView.text = data.title } // 页面销毁时取消协程,避免内存泄漏 override fun onDestroy() { super.onDestroy() mainScope.cancel() }
为什么符合你的要求?
- 没有使用Interactors、AsyncTask等额外类
- 完全看不到
new Handler(Looper.getMainLooper()).post(...)或RunOnUiThread这类包装代码 - 用
withContext替代await,不会冻结UI线程——它是挂起函数,只会暂停当前协程,不会阻塞UI线程的事件循环 - 代码逻辑接近同步写法,可读性极强
备选方案(Java开发者适用)
如果还在使用Java,可以用RxJava实现类似效果,同样无需手动包装线程切换:
// 定义数据库读取任务 Observable.fromCallable(() -> readDb()) .subscribeOn(Schedulers.io()) // 指定Worker线程执行ReadDb .observeOn(AndroidSchedulers.mainThread()) // 指定UI线程执行SetData .subscribe( data -> setData(data), throwable -> {/* 处理异常逻辑 */} );
内容的提问来源于stack exchange,提问作者JonZarate
相关产品推荐
相关产品推荐

