refactor(main): 将Thread替换为lifecycleScope并优化协程处理
- 替换CollectFragment中的Thread为activity.lifecycleScope.launch - 在MainActivity中添加FaceServer相关依赖和协程调度器 - 修改环境切换对话框以支持人脸数据重置功能 - 将照片拍摄和食物向量保存操作从Thread迁移到lifecycleScope - 优化人脸识别数据更新逻辑,移除不必要的线程创建 - 修改onTakePhotoSuccess方法为suspend函数并调整UI更新方式 - 更新主线程操作使用withContext(Dispatchers.Main)替代runOnUiThread - 在MainScreenPresentation中添加相机暂停功能 - 修复SensorScaleUtils中标定调用问题 - 扩展UserViewModel的人脸数据获取接口,支持回调处理
This commit is contained in:
@@ -68,10 +68,14 @@ import com.sw.plate.utils.LightManager
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
||||
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
|
||||
import com.sw.plate.utils.arcface.faceserver.FaceServer
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@@ -205,7 +209,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
updateDateTime()
|
||||
binding.tvTitleTime.setOnClickListener {
|
||||
EnvSwitchDialog(this).show()
|
||||
EnvSwitchDialog(context = this, onEnvChanged = {
|
||||
showWaitingDialog("重置人脸数据中……")
|
||||
FaceServer.getInstance().clearAllFaces()
|
||||
viewModel.getUserFaceCache(pageNo = 1, onSuccess = {
|
||||
hideWaitingDialog()
|
||||
ToastUtils.showToast("人脸数据已更新")
|
||||
}, onFailure = { errMsg ->
|
||||
ToastUtils.showToast(errMsg)
|
||||
})
|
||||
}).show()
|
||||
}
|
||||
binding.ivSetting.setOnClickListener {
|
||||
isRefreshPage = false
|
||||
@@ -410,12 +423,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
LightManager.closeRedLight()
|
||||
LightManager.openGreenLight()
|
||||
showWaitingDialog("识别中,请稍后……")
|
||||
lifecycleScope.launch {
|
||||
delay(5000)
|
||||
withContext(Dispatchers.Main) {
|
||||
hideWaitingDialog()
|
||||
}
|
||||
}
|
||||
takePhoto(successCallback = { photoUri ->
|
||||
Thread {
|
||||
lifecycleScope.launch {
|
||||
onTakePhotoSuccess(photoUri)
|
||||
}.start()
|
||||
}
|
||||
failCount = 0
|
||||
}, failureCallback = {
|
||||
log("registerDataChange main,拍照异常,请重试")
|
||||
//ToastUtils.showToast("拍照异常,请重试")
|
||||
failCount++
|
||||
hideWaitingDialog()
|
||||
@@ -809,9 +829,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
if (checkedItem?.isFromSearch == true) {
|
||||
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
||||
Thread {
|
||||
lifecycleScope.launch {
|
||||
saveFoodVector(checkedItem!!)
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
@@ -1074,44 +1094,44 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
if (list.isEmpty()) {
|
||||
return@runOnUiThread
|
||||
}
|
||||
updateFaceData(list)
|
||||
lifecycleScope.launch {
|
||||
updateFaceData(list)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFaceData(list: List<UserFaceModel>) {
|
||||
Thread {
|
||||
val faceList = mutableListOf<FaceEntity>()
|
||||
try {
|
||||
list.forEach { model ->
|
||||
if (model.faceDeleted == true) {
|
||||
//删除数据
|
||||
FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId)
|
||||
} else {
|
||||
//保存数据
|
||||
val faceEntity = FaceEntity(
|
||||
model.userId, null, Base64.decode(model.faceFeatureStr)
|
||||
).also {
|
||||
//1-会员、2-临时用户
|
||||
it.userType = if (model.member) "1" else "2"
|
||||
it.cardNo = model.cardNo
|
||||
}
|
||||
faceList.add(faceEntity)
|
||||
val faceList = mutableListOf<FaceEntity>()
|
||||
try {
|
||||
list.forEach { model ->
|
||||
if (model.faceDeleted == true) {
|
||||
//删除数据
|
||||
FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId)
|
||||
} else {
|
||||
//保存数据
|
||||
val faceEntity = FaceEntity(
|
||||
model.userId, null, Base64.decode(model.faceFeatureStr)
|
||||
).also {
|
||||
//1-会员、2-临时用户
|
||||
it.userType = if (model.member) "1" else "2"
|
||||
it.cardNo = model.cardNo
|
||||
}
|
||||
faceList.add(faceEntity)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
try {
|
||||
if (faceList.isNotEmpty()) {
|
||||
FaceDatabase.getInstance(this).faceDao().insert(faceList)
|
||||
}
|
||||
recognizeViewModel.refreshFaceList();
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
try {
|
||||
if (faceList.isNotEmpty()) {
|
||||
FaceDatabase.getInstance(this).faceDao().insert(faceList)
|
||||
}
|
||||
}.start()
|
||||
recognizeViewModel.refreshFaceList();
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendFaceData(faceData: String) {
|
||||
@@ -1125,16 +1145,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
private var tcpClient: TcpClient? = null
|
||||
|
||||
private fun onTakePhotoSuccess(photoUri: Uri) {
|
||||
private suspend fun onTakePhotoSuccess(photoUri: Uri) {
|
||||
lastPhotoUri = photoUri
|
||||
log("registerDataChange main,takePhoto耗时:${System.currentTimeMillis() - startTime}")
|
||||
startTime = System.currentTimeMillis()
|
||||
log("registerDataChange photoUri = ${photoUri.path}")
|
||||
// viewModel.getIdentifiedFoodList()
|
||||
lifecycleScope.launch {
|
||||
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
||||
queryFoodData(bitmap)
|
||||
}
|
||||
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
||||
queryFoodData(bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,7 +1181,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
hideWaitingDialog()
|
||||
log("registerDataChange photoUri 识别数据名称:$foodName")
|
||||
runOnUiThread {
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.flPay.run {
|
||||
//0-计费,1-不计费
|
||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||
@@ -1176,7 +1194,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
LightManager.closeRedLight()
|
||||
//binding.layoutRescan.visibility = View.VISIBLE
|
||||
|
||||
runOnUiThread {
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.tvToSearch.let {
|
||||
it.text = "未识别到,手动搜索"
|
||||
it.visible()
|
||||
|
||||
@@ -118,11 +118,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
collectionAdapter.notifyItemChanged(index)
|
||||
}
|
||||
// settingActivity?.hideWaitingDialog()
|
||||
Thread {
|
||||
activity?.lifecycleScope?.launch {
|
||||
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
||||
getImageVector(index, bitmap)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
settingActivity?.hideWaitingDialog()
|
||||
|
||||
@@ -1041,6 +1041,7 @@ class MainScreenPresentation(
|
||||
return@runOnUiThread
|
||||
}
|
||||
}
|
||||
pauseCamera()
|
||||
step3ShowRecognizeResult(userId)
|
||||
})
|
||||
|
||||
@@ -1313,6 +1314,7 @@ class MainScreenPresentation(
|
||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
||||
lastFaceTrackId = -1
|
||||
//resumeCamera()
|
||||
Timber.tag(TAG)
|
||||
.d("postUserData userNutritionData是否null: ${userNutrition == null}, currentFood是否null: ${currentFood == null},currentUserId是否null:${currentUserId == null}")
|
||||
if (userNutrition == null || currentFood == null || currentUserId == null) {
|
||||
|
||||
@@ -87,8 +87,7 @@ object SensorScaleUtils {
|
||||
// Thread.sleep(1000)
|
||||
|
||||
// TODO: 暂时不标定---------
|
||||
//zero()
|
||||
|
||||
zero()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,54 +91,68 @@ class UserViewModel : BaseViewModel() {
|
||||
/**
|
||||
* 获取人脸数据
|
||||
*/
|
||||
fun getUserFaceCache(pageNo: Int = 1, pageSize: Int = PAGE_SIZE) {
|
||||
fun getUserFaceCache(
|
||||
pageNo: Int = 1,
|
||||
pageSize: Int = PAGE_SIZE,
|
||||
onSuccess: () -> Unit = {},
|
||||
onFailure: (String) -> Unit = {}
|
||||
) {
|
||||
// Initialize current page number
|
||||
var currentPageNo = pageNo
|
||||
// Debug log to track current page
|
||||
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
|
||||
// Launch a coroutine to perform the face data retrieval
|
||||
launch {
|
||||
// Set loading state to false
|
||||
_loadFaceResult.value = false
|
||||
//获取全量数据时,时间戳改为0
|
||||
SpTool.lastFaceTimestamp = 0
|
||||
val response = repository.getUserFaceCache(currentPageNo)
|
||||
if (parseResponse(response)) {
|
||||
// 获取成功一次后缓存状态
|
||||
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
||||
withContext(Dispatchers.Default) {
|
||||
val list: List<UserFaceModel> = response.data ?: emptyList()
|
||||
if (pageNo == 1 && list.isEmpty()) {
|
||||
//ToastUtils.showToast("查询人脸数据为空")
|
||||
return@withContext
|
||||
}
|
||||
//val item = list.map { it.member }
|
||||
//Timber.tag(TAG).d("getUserFaceCache item = $item")
|
||||
val faceEntity = list.map {
|
||||
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureStr)).also { item ->
|
||||
item.userType = if (it.member) "1" else "2"
|
||||
item.cardNo = it.cardNo
|
||||
}
|
||||
}
|
||||
faceApi.updateFaceData(currentPageNo, faceEntity)
|
||||
if (list.size >= pageSize) {
|
||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||
currentPageNo++
|
||||
getUserFaceCache(currentPageNo)
|
||||
return@withContext
|
||||
}
|
||||
//查询完成所有数据,保存时间戳
|
||||
if (list.isNotEmpty()) {
|
||||
//非空最后一条数据的是时间戳,空使用上次list最后一条时间戳
|
||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||
}
|
||||
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
||||
_loadFaceResult.value = true
|
||||
val check = parseResponse(response)
|
||||
if (!check) {
|
||||
// 获取失败
|
||||
onFailure("获取人脸数据失败,${response.msg}(${response.code})")
|
||||
return@launch
|
||||
}
|
||||
// 获取成功一次后缓存状态
|
||||
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
||||
withContext(Dispatchers.Default) {
|
||||
val list: List<UserFaceModel> = response.data ?: emptyList()
|
||||
if (pageNo == 1 && list.isEmpty()) {
|
||||
//ToastUtils.showToast("查询人脸数据为空")
|
||||
onFailure("查询人脸数据为空")
|
||||
return@withContext
|
||||
}
|
||||
|
||||
//val item = list.map { it.member }
|
||||
//Timber.tag(TAG).d("getUserFaceCache item = $item")
|
||||
val faceEntity = list.map {
|
||||
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureStr)).also { item ->
|
||||
item.userType = if (it.member) "1" else "2"
|
||||
item.cardNo = it.cardNo
|
||||
}
|
||||
}
|
||||
faceApi.updateFaceData(currentPageNo, faceEntity)
|
||||
if (list.size >= pageSize) {
|
||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||
currentPageNo++
|
||||
getUserFaceCache(currentPageNo)
|
||||
return@withContext
|
||||
}
|
||||
//查询完成所有数据,保存时间戳
|
||||
if (list.isNotEmpty()) {
|
||||
//非空最后一条数据的是时间戳,空使用上次list最后一条时间戳
|
||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||
}
|
||||
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
||||
_loadFaceResult.value = true
|
||||
onSuccess()
|
||||
}
|
||||
// val nextPageIndex = response.result?.nextPageIndex ?: -1
|
||||
// if (nextPageIndex > 0) {
|
||||
// getUserFaceCache(nextPageIndex)
|
||||
// } else {
|
||||
// _loadFaceResult.value = true
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user