首页 > 解决方案 > 在 CameraX analyze() 中执行异步代码的最佳方法是什么?

问题描述

我正在使用 CameraX 的图像分析用例,它在我的自定义类中不断调用该analyze()方法。Analyzer在内部analyze(),在做任何其他事情之前,我需要向连接的设备发送请求并等待其响应;延迟非常低,我已经在同步进行,没有任何问题,但有人告诉我最好让它异步,以防设备响应太慢。

我知道 MLKit 的process()返回 aTask<List<T>>并且我已经调用onSuccessListener { }了它,所以我想知道是否可以使用类似的方法(我不能Task<T>从我的函数中返回 a,如何创建一个?)。否则你会建议线程、协程或其他东西吗?

编辑:下面有一个我正在尝试做的简化示例。对于相机发送的给定帧,我只需要在线执行当前分析,然后返回,以便analyze()在下一帧再次调用它,它将在该帧上执行下一次分析。

它可能看起来很老套,但它适用于在单一用途设备(我们称之为Dev A)上连续在前台运行的应用程序,没有通过触摸或其他传统方式提供用户交互,因此它需要某种触发器来开始执行操作是必须的。

触发器也可能是当第一个图像分析成功时,但是整天从实时摄像机源运行 MLKit 或 TFLite 模型会使Dev A过热。到目前为止,最好的解决方案似乎是等待触发器来自独立运行的外部设备( Dev B )。

由于Dev B可能会延迟一些响应,因此我需要与它异步通信,因此首先提出问题的原因。虽然肯定有几个架构上的细微差别需要讨论,但问题的当前根源是我无法决定(或者更确切地说,我不知道)如何以非阻塞方式处理与Dev B的重复“连接” 。

我的意思是,我可以像其他需要多线程的情况一样对待这个问题,或者涉及相机的事实可能会带来额外的威胁吗?背压策略设置为STRATEGY_KEEP_ONLY_LATEST,因此理论上如果当前调用analyze()尚未完成,则新帧被丢弃并且即使在方法内部我仍在等待对Dev B的异步调用完成,也没有发生任何坏事,或者我错过了什么吗?

var connected = false
lateinit var result: Boolean
var analysis1 = true
var analysis2 = true

override fun analyze() {
    if (!connected) {
        result = connectToDevice() // needs to be async
        connected = true
    }

    // need positive result to proceed, otherwise start over
    if (!result) {
        connected = false
        return   
    }     
    
    if (analysis1) {
        // perform analysis #1...

        analysis1 = false
        // when an analysis is done, exit early and perform next analysis on next frame
        return
    }

    if (analysis2) {
        // perform analysis #2...

        analysis2 = false
        // same as above
        return
    }

    // when all analyses are done, reset all flags to start over
    connected = false
    analysis1 = true
    analysis2 = true
}

标签: androidkotlinasynchronousandroid-camerax

解决方案


推荐阅读