我想做的是:
然而,我正在努力使它在我的存储库中工作。我的功能如下:
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()函数在源代码中的样子:
@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的吗?
发布于 2022-04-18 06:50:13
AsyncTask在API级别30中被否决,请考虑使用Kotlin或其他Kotlin并发实用程序。如果没有AsyncTask,它将如下所示:
在Palette.Builder类中:
suspend fun generatePalette() = withContext(Dispatchers.IO) {
generate()
}存放处:
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
suspend fun insertAgent(...)发布于 2022-04-18 14:15:21
如果由于某些原因无法修改Palette.Builder类的源代码,则可以编写这样的挂起适应函数。suspendCancellableCoroutine用于将基于回调的函数转换为挂起函数,方法是挂起协同线并让您直接使用挂起的连续函数。在回调触发时恢复协同线,如果协同线在恢复之前被取消,则取消该工作。
suspend fun Palette.Builder.await(): Palette? = suspendCancellableCoroutine { cont ->
val task = generate { cont.resume(it) }
cont.invokeOnCancellation(task.cancel())
}然后,可以以同步方式编写其他函数,并在必要时使用withContext:
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()中。
https://stackoverflow.com/questions/71908073
复制相似问题