合并runBlocking
和withContext
似乎在分发消息
Note: end time exceeds epoch:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
withContext(DefaultDispatcher) {
null
}
}
}
}
我使用了许多这样的协程,并且logcat被垃圾邮件了,有什么办法可以避免这种情况?另一种方法,例如:
var projects: List<ProjectEntity>? = runBlocking {
withContext(DefaultDispatcher) {
//Get the ProjectEntity list
}
}
projects?.let {
onResult(projects)
}
编辑
我尝试根据您的评论(谢谢),但无法获得与上述示例类似的结果:
Log.d("Coroutines", "getMostRecent start")
var localeProject: ProjectEntity? = null
launch {
withContext(CommonPool) {
Log.d("Coroutines", "getRecentLocaleProject")
localeProject = getRecentLocaleProject()
}
}
Log.d("Coroutines", "check localeProject")
if (localeProject != null) {
//Show UI
}
在Logcat中:
D/Coroutines: getMostRecent start
D/Coroutines: check localeProject
D/Coroutines: getRecentLocaleProject
我想分离异步和同步内容,这是不可能的吗?我真的想尽可能避免存储库中的所有回调。
答案 0 :(得分:1)
Markos注释正确,您不应阻止UI线程。
您应该使用launch
或async
并使用withContext
切换回UI线程。
class MainActivity : ScopedAppActivity() {
fun asyncShowData() = launch { // Is invoked in UI context with Activity's job as a parent
// actual implementation
}
suspend fun showIOData() {
val deferred = async(Dispatchers.IO) {
// impl
}
withContext(Dispatchers.Main) {
val data = deferred.await()
// Show data in UI
}
}
}
请注意,该示例使用了新的协程API(> 0.26.0),该API重命名了Dispatchers。因此,Dispatchers.Main
对应于旧版本中的UI
。
答案 1 :(得分:0)
let func = () => (<Image source={require('../images/image.png')} />)
<View>
{func()}
{func()}
{func()}
{func()}
{func()}
</View>
我想分离异步和同步内容,没有这样的方法吗?
var localeProject: ProjectEntity? = null
launch {
withContext(CommonPool) {
localeProject = getRecentLocaleProject()
}
}
if (localeProject != null) {
//Show UI
}
协程在语义上就像是launch
插入了一个线程。直觉告诉您,刚开始设置start
的线程后就不能指望它,对于协程来说也是如此。它甚至更强大:保证不要看到localeProject != null
,因为localeProject != null
仅向事件循环添加了一个新事件。在您当前的方法完成之前,将不会处理该事件。
因此,您可以忘记从异步代码初始化的顶级launch
。甚至val
都无法使用,因为您无法保证会看到它已经初始化。您必须使用最宽松的类型:可为空的lateinit var
s。