【问题标题】:Do I still need to use background thread if I use coroutine to read/write Realm in Android to avoid blocking UI?如果我在Android中使用协程读/写Realm以避免阻塞UI,是否还需要使用后台线程?
【发布时间】:2020-01-08 21:02:01
【问题描述】:

我脑子里有问题,我不知道如何测试它。

假设我有一个函数getData,它从一个领域对象加载数据,它需要 5 秒。

如果没有协程,我需要在后台线程中调用这个方法以避免阻塞UI。

如果我将getData 更改为挂起函数,并在主线程上调用它,它是否仍会冻结 UI 线程 5 秒?还是会像在getData函数内部调用delay(5000)一样,不会阻塞UI线程?

我想创建一个简单的项目来验证这一点,但我没有足够大的数据来产生 5 秒的延迟。

【问题讨论】:

  • 虽然如果从 Realm 获取数据需要 5 秒,那么我很好奇你拥有的数据量。 Realm 不喜欢在线程之间折腾,因为它是线程受限的,但是查询应该相当懒惰。

标签: android realm kotlin-coroutines


【解决方案1】:

如果我把getData改成suspend函数,在主线程上调用,它还会冻结UI线程5秒吗?

是的,协程无法撤消给定代码进行阻塞函数调用的事实。这是您可以用来将阻塞调用移交给后台线程然后继续在 UI 线程上使用它的典型习惯用法:

myScope.launch {
    val result = withContext(Dispatchers.IO) {
        // blocking call here
    }
    // use the result to update the GUI here
}

【讨论】:

    【解决方案2】:

    我认为这取决于您的意思

    如果我将getData 更改为挂起功能

    • 如果你只是在函数中添加关键字suspend,它不会改变任何东西,即线程将被阻塞,直到你得到响应。
    • 如果您将函数重写为“可暂停”,那么它将
      1. 触发请求
      2. 暂停自身(不阻塞线程)
      3. 收到回复后恢复

    您可以使用 Coroutines 库中的 suspendCoroutine 函数来实现此目的。

    抽象的例子如下:

    suspend fun getData(): String = suspendCoroutine { continuation ->
    
            // 1. Trigger event
            serverApi.getData().onResult(
    
                // 3. Resume either with data or error, after callback received from serverApi
                onSuccess = {
                    continuation.resume("Data") 
                },
                onError = {
                    continuation.resume("Error")
                } 
            )
    
            // 2. Suspend after block is finished
        }
    

    附:可能在您的情况下(从数据库获取数据)上面将不起作用,因为没有什么可以挂起(函数一直很忙,与网络请求不同)。

    【讨论】:

      猜你喜欢
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      相关资源
      最近更新 更多