feat(face): 优化人脸库更新同步及识别引擎刷新机制
- 引入进程级互斥锁 FaceSyncLock,串行化 MQTT 实时更新与 HTTP 增量轮询人脸库写操作,避免重复入库 - 优化 MQTT 实时消息处理逻辑,批内去重并加入乱序守卫,确保数据正确性与一致性 - 将识别引擎内存刷新调度防抖至 scheduleFaceRefresh,合并短时间内多次变更减少资源消耗 - 在 BaseActivity 中实现防抖刷新机制,统一 MQTT、HTTP增量和定时轮询三路触发入口 - 移除应用启动时人脸 MQTT 订阅初始化,改为首次全量同步完成后启动,防止并发竞态 - LoginByFaceActivity 和 DeviceInitActivity 适配新增机制,优化人脸数据同步及识别引擎刷新流程
This commit is contained in:
@@ -4,6 +4,8 @@ import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.TextUtils
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
@@ -399,6 +401,19 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
|
||||
val recognizeViewModel by viewModels<RecognizeViewModel>()
|
||||
|
||||
/**
|
||||
* 引擎内存刷新防抖:合并短时间内连续的人脸变更(MQTT 实时 + HTTP 增量补拉 + 定时轮询),
|
||||
* 避免多次全量重载 ArcSoft 引擎内存(removeFaceFeature(-1) + registerFaceFeature 非原子)。
|
||||
*/
|
||||
private val faceRefreshHandler = Handler(Looper.getMainLooper())
|
||||
private val faceRefreshRunnable = Runnable { recognizeViewModel.refreshFaceList() }
|
||||
|
||||
/** 防抖调度引擎内存刷新(2s 内连续变更合并为一次) */
|
||||
protected fun scheduleFaceRefresh() {
|
||||
faceRefreshHandler.removeCallbacks(faceRefreshRunnable)
|
||||
faceRefreshHandler.postDelayed(faceRefreshRunnable, 2000)
|
||||
}
|
||||
|
||||
fun startFaceTask() {
|
||||
faceTaskJob =
|
||||
intervalExecutor.startIntervalTaskWithInitialDelay(initialDelay, dealyMillis) {
|
||||
@@ -418,7 +433,7 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
pageNo = pageNo,
|
||||
timestamp = timestamp
|
||||
) {
|
||||
recognizeViewModel.refreshFaceList()
|
||||
scheduleFaceRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.platecabinet.GlobalData
|
||||
import com.sw.platecabinet.member.databinding.ActivityDeviceInitBinding
|
||||
import com.sw.platecabinet.member.databinding.ItemTitleTimeBinding
|
||||
import com.sw.platecabinet.mqtt.FaceMqttSubscriber
|
||||
import com.sw.platecabinet.utils.SpTool
|
||||
import timber.log.Timber
|
||||
|
||||
@@ -76,6 +77,9 @@ class DeviceInitActivity : BaseActivity<ActivityDeviceInitBinding>() {
|
||||
}
|
||||
|
||||
private fun goLoginActivity() {
|
||||
// 首次全量同步(如需)已完成,此时启动人脸 MQTT 实时订阅,
|
||||
// 避免与首次全量同步的 clearFaceData 产生并发写竞态
|
||||
FaceMqttSubscriber.start()
|
||||
val intent = Intent(this, LoginByFaceActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
|
||||
@@ -146,16 +146,13 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
|
||||
/**
|
||||
* MQTT 实时同步后的人脸库已落库,防抖重载识别引擎内存(合并短时间内连续变更)
|
||||
* MQTT 实时同步后的人脸库已落库,防抖重载识别引擎内存(合并短时间内连续变更)。
|
||||
* scheduleFaceRefresh 定义于 BaseActivity,统一 MQTT/HTTP 增量/定时轮询三路刷新入口。
|
||||
*/
|
||||
private val faceRefreshHandler = Handler(Looper.getMainLooper())
|
||||
private val faceRefreshRunnable = Runnable { recognizeViewModel.refreshFaceList() }
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onFaceChanged(event: FaceChangedEvent) {
|
||||
Timber.d("onFaceChanged 收到人脸实时变更,2s 后刷新引擎内存")
|
||||
faceRefreshHandler.removeCallbacks(faceRefreshRunnable)
|
||||
faceRefreshHandler.postDelayed(faceRefreshRunnable, 2000)
|
||||
scheduleFaceRefresh()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +167,7 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
Timber.d("onFaceSyncTrigger MQTT 已连接,执行 HTTP 增量补拉 timestamp=$timestamp")
|
||||
netViewModelV2.getFaceIncrementList(pageNo = 1, timestamp = timestamp) {
|
||||
recognizeViewModel.refreshFaceList()
|
||||
scheduleFaceRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user