我有以下场景(查看下面的代码):
1.从CameraX的ImageAnalyzer
用例循环中获取ImageProxy
1.分析图像(大约需要20毫秒)并返回一些信息,close()
ImageProxy
1.通过AsyncTask分析提取的信息(大约需要500到3000毫秒)
1.如果成功,显示结果
我有一些片段依赖于任务1和2的成功程度(特别是一个PreviewView片段和一些结果页面)。目前他们得到ViewModel
的通知。当图像被任务1或2分析时。我用viewModel.analyzerState.postValue(<newState>)
设置了一个状态。这当然不是理想的,因为我还需要在我的任务中监听该状态,以防前面的图像生成了可以向用户显示的结果。
我现在的问题是:
当结果准备就绪时,任务1或2可能仍在运行,并产生另一个结果,这将触发UI更新两次。我不希望这样,但我仍然希望任务并行运行,以防前一个任务失败(这种情况经常发生)。当我确定有结果时,我希望任务被取消(我已经在AsyncTask上调用了cancel()
,但没有起作用)我认为我的问题是将ViewModel
用作线程间通信的消息传递工具,因为我在Task 1.和Task 2.中设置了状态,并在循环中侦听它。
我能找到的唯一信息是使用Kotlin协程,这显然是为与ViewModel
一起工作而制作的,但我使用的是Java。
解决这类问题的标准方法是什么?我如何在不同的线程和片段之间 * 安全地 * 通信?
代码:
void analyzeImage(ImageProxy imageProxy) { // loop called by CameraX
if (viewModel.analyzerState.getValue() == 'done') {
imageProxy.close();
return;
}
viewModel.analyzerState.postValue('extracting');
Data data = extractData(imageProxy);
imageProxy.close();
if (data.isValid()) {
viewModel.analyzerState.postValue('analyzing');
new DataAnalyzeTask.execute(data);
} else {
viewModel.analyzerState.postValue('idle');
}
}
// UI listens with
viewModel.analyzerState.observe(getViewLifecycleOwner(), state -> { /*...*/ } );
1条答案
按热度按时间eulz3vhy1#
这花了我一些时间和很多修改,但现在我有了一个适合我的目的的解决方案。所以不是使用
AsyncTask
和ViewModel
进行通信,我实现了我自己的Task
类,它基本上只是一个带有一些回调函数的Runnable
,这些回调函数允许我与UI通信,然后UI通过ViewModel
传播数据更改(在主线程上)。为了确保我在主线程上,我在主线程处理程序中执行回调:我的定制
Task
通过ExecutorService
在线程池中执行:我认为使用
ListenableFuture
可能有一个更简单的解决方案(因为我或多或少地用Task
和TaskCallback
类重新实现了这些解决方案),但我现在不想将Guava添加到我的项目中。为了确保可以取消任务,我使用了
AtomicBoolean
,并在得到一些结果后将值设置为false:以下是一些有用的资源:
https://developer.android.com/guide/background/asynchronous/java-threadshttps://developer.android.com/guide/background/asynchronous/listenablefuture