首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用异步任务侦听器从coroutine返回和挂起?

如何使用异步任务侦听器从coroutine返回和挂起?
EN

Stack Overflow用户
提问于 2022-04-18 05:57:13
回答 2查看 696关注 0票数 1

我想做的是:

  1. 从API加载代理图标
  2. 使用调色板,确定什么是充满活力的样本。
  3. 设置此背景RGB颜色并将其保存到数据库中。
  4. 数据库将被更新,更新流程并将新的更新推送到UI。
  5. UI获取它,然后将其设置为回收器视图。

然而,我正在努力使它在我的存储库中工作。我的功能如下:

代码语言:javascript
复制
suspend fun updateAgentBackground(agent: Agent, successResult: SuccessResult) {
    if (agent.backgroundRgb == null) {
        withContext(Dispatchers.IO) {
            Palette.Builder(successResult.drawable.toBitmap()).generate { palette ->
                val rgb = palette?.vibrantSwatch?.rgb
                if (rgb != null) {
                    val agentWithBackground = agent.copy(backgroundRgb = rgb)
                    agentDao.insertAgent(agentWithBackground.toAgentEntity())
                }
            }
        }
    }
}

但是,它在运行时在agentDao.insertAgent()上崩溃,因为它说它在主线程上运行DB操作。我也不能在generate()回调中使用withContext(Dispatchers.IO)包装这个方法,因为它不在一个协同体中。

这是Palette.Builder().generate()函数在源代码中的样子:

代码语言:javascript
复制
@NonNull
public AsyncTask<Bitmap, Void, Palette> generate(
        @NonNull final PaletteAsyncListener listener) {
    if (listener == null) {
        throw new IllegalArgumentException("listener can not be null");
    }

    return new AsyncTask<Bitmap, Void, Palette>() {
        @Override
        @Nullable
        protected Palette doInBackground(Bitmap... params) {
            try {
                return generate();
            } catch (Exception e) {
                Log.e(LOG_TAG, "Exception thrown during async generate", e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(@Nullable Palette colorExtractor) {
            listener.onGenerated(colorExtractor);
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
}

public interface PaletteAsyncListener {
    void onGenerated(@Nullable Palette palette);
}

所以我把PaletteAsyncListener传递给它,它只有一个函数onGenerated()。在某种程度上,我希望这个方法挂起协同线,并将更新的背景返回给我Agent。或者以某种方式在主线程的回调中调用我的DB方法agentDao.insertAgent()

我能以某种方式混合和匹配源代码是如何使用AsyncTask的吗?

EN

回答 2

Stack Overflow用户

发布于 2022-04-18 06:50:13

AsyncTask在API级别30中被否决,请考虑使用Kotlin或其他Kotlin并发实用程序。如果没有AsyncTask,它将如下所示:

Palette.Builder类中:

代码语言:javascript
复制
suspend fun generatePalette() = withContext(Dispatchers.IO) {
    generate()
}

存放处:

代码语言:javascript
复制
suspend fun updateAgentBackground(agent: Agent, successResult: SuccessResult) {
    if (agent.backgroundRgb == null) {
        val palette = Palette.Builder(successResult.drawable.toBitmap()).generatePalette()
        val rgb = palette?.vibrantSwatch?.rgb
        if (rgb != null) {
            val agentWithBackground = agent.copy(backgroundRgb = rgb)
            agentDao.insertAgent(agentWithBackground.toAgentEntity())
        }
    }
}

也是在AgentDao标记函数insertAgent中作为suspend

代码语言:javascript
复制
suspend fun insertAgent(...)
票数 1
EN

Stack Overflow用户

发布于 2022-04-18 14:15:21

如果由于某些原因无法修改Palette.Builder类的源代码,则可以编写这样的挂起适应函数。suspendCancellableCoroutine用于将基于回调的函数转换为挂起函数,方法是挂起协同线并让您直接使用挂起的连续函数。在回调触发时恢复协同线,如果协同线在恢复之前被取消,则取消该工作。

代码语言:javascript
复制
suspend fun Palette.Builder.await(): Palette? = suspendCancellableCoroutine { cont ->
    val task = generate { cont.resume(it) }
    cont.invokeOnCancellation(task.cancel())
}

然后,可以以同步方式编写其他函数,并在必要时使用withContext

代码语言:javascript
复制
suspend fun updateAgentBackground(agent: Agent, successResult: SuccessResult) {
    if (agent.backgroundRgb == null) {
        val palette = Palette.Builder(successResult.drawable.toBitmap()).await()
        val rgb = palette?.vibrantSwatch?.rgb
        if (rgb != null) {
            val agentWithBackground = agent.copy(backgroundRgb = rgb)
            agentDao.insertAgent(agentWithBackground.toAgentEntity())
        }
    }
}

确保将AgentDao.insertAgent()标记为suspend函数,这样就可以调用协同线中的任何位置,而不必担心调用线程。

以上代码假设toBitmap()是非阻塞的.如果它阻塞,则应该将其包装在适当的withContext()中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71908073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档