Android 科特林山脉:注:结束时间超过历元:

Android 科特林山脉:注:结束时间超过历元:,android,kotlin,kotlinx.coroutines,Android,Kotlin,Kotlinx.coroutines,将runBlocking和withContext组合起来似乎可以分派消息 注意:结束时间超过历元: class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) r

runBlocking
withContext
组合起来似乎可以分派消息
注意:结束时间超过历元:

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)
}
在Logcat中:

D/Coroutines: getMostRecent start
D/Coroutines: check localeProject
D/Coroutines: getRecentLocaleProject

我想分开异步和同步的东西,没有这样的方法吗?我真的希望尽可能避免我的存储库中的所有回调操作。

Markos comment是正确的,您不应该阻止UI线程

您应该使用
launch
async
并使用
withContext
切换回UI线程

您可以在这里找到一些示例:

请注意,该示例使用了新的协同程序API(>0.26.0),该API重命名了Dispatchers。因此
Dispatchers.Main
对应于旧版本中的
UI

var localeProject: ProjectEntity? = null
launch {
    withContext(CommonPool) {
        localeProject = getRecentLocaleProject()
    }
}
if (localeProject != null) {
    //Show UI
}
我想分开异步和同步的东西,没有这样的方法吗

当您
启动
一个协同程序时,语义上就像您
启动
一个线程。直觉告诉您不能期望
localeProject!=空值
仅在启动设置它的线程之后,对于协同程序也是如此。它甚至更强大:保证您永远不会看到
localeProject!=null
,因为
启动
只会将新事件添加到事件循环中。在当前方法完成之前,不会处理该事件


因此,您可以忽略从异步代码初始化的顶级
val
s。即使是
lateinit var
s也不能工作,因为您无法保证看到它已经初始化。您必须使用最松散的类型:可空
var
s。

不要在Android UI回调中使用
runBlocking
。它会阻塞UI线程。您不能直接分配异步计算的结果,因此您的
项目
示例不能这样工作。例如,你可以这样做(注意:我会使用
scopedappacitivity()
,只使用
launch
,而不是
GlobalScope.launch(Dispatchers.Main)
)我的示例工作正常,但它是线程阻塞,正如@MarkoTopolnik所说的(不清楚,谢谢),我的日志最后被垃圾邮件发送了那个神秘的消息,感谢所有的评论,我改变了我所有的堆栈:数据库层是完全同步的,但带有挂起函数和演示者层处理异步逻辑。神秘消息
注意:结束时间超过了历元:
消失但保持神秘…这里的
ScopedAppActivity
是什么?这太复杂了,您只需要
val ioResult=withContext(IO){blockingCall()}
。不需要它来自的
async
@TimCastelijns。我想将我的协同路由限制在我的存储库层中,避免对基本调用的回调。
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
        }
    }
}
var localeProject: ProjectEntity? = null
launch {
    withContext(CommonPool) {
        localeProject = getRecentLocaleProject()
    }
}
if (localeProject != null) {
    //Show UI
}