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.ToastUtils
|
||||||
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
||||||
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
|
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 com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
@@ -205,7 +209,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
updateDateTime()
|
updateDateTime()
|
||||||
binding.tvTitleTime.setOnClickListener {
|
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 {
|
binding.ivSetting.setOnClickListener {
|
||||||
isRefreshPage = false
|
isRefreshPage = false
|
||||||
@@ -410,12 +423,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
LightManager.openGreenLight()
|
LightManager.openGreenLight()
|
||||||
showWaitingDialog("识别中,请稍后……")
|
showWaitingDialog("识别中,请稍后……")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(5000)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
hideWaitingDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
takePhoto(successCallback = { photoUri ->
|
takePhoto(successCallback = { photoUri ->
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
onTakePhotoSuccess(photoUri)
|
onTakePhotoSuccess(photoUri)
|
||||||
}.start()
|
}
|
||||||
failCount = 0
|
failCount = 0
|
||||||
}, failureCallback = {
|
}, failureCallback = {
|
||||||
|
log("registerDataChange main,拍照异常,请重试")
|
||||||
//ToastUtils.showToast("拍照异常,请重试")
|
//ToastUtils.showToast("拍照异常,请重试")
|
||||||
failCount++
|
failCount++
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
@@ -809,9 +829,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
if (checkedItem?.isFromSearch == true) {
|
if (checkedItem?.isFromSearch == true) {
|
||||||
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
saveFoodVector(checkedItem!!)
|
saveFoodVector(checkedItem!!)
|
||||||
}.start()
|
}
|
||||||
}
|
}
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
@@ -1074,44 +1094,44 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
updateFaceData(list)
|
lifecycleScope.launch {
|
||||||
|
updateFaceData(list)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFaceData(list: List<UserFaceModel>) {
|
private fun updateFaceData(list: List<UserFaceModel>) {
|
||||||
Thread {
|
val faceList = mutableListOf<FaceEntity>()
|
||||||
val faceList = mutableListOf<FaceEntity>()
|
try {
|
||||||
try {
|
list.forEach { model ->
|
||||||
list.forEach { model ->
|
if (model.faceDeleted == true) {
|
||||||
if (model.faceDeleted == true) {
|
//删除数据
|
||||||
//删除数据
|
FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId)
|
||||||
FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId)
|
} else {
|
||||||
} else {
|
//保存数据
|
||||||
//保存数据
|
val faceEntity = FaceEntity(
|
||||||
val faceEntity = FaceEntity(
|
model.userId, null, Base64.decode(model.faceFeatureStr)
|
||||||
model.userId, null, Base64.decode(model.faceFeatureStr)
|
).also {
|
||||||
).also {
|
//1-会员、2-临时用户
|
||||||
//1-会员、2-临时用户
|
it.userType = if (model.member) "1" else "2"
|
||||||
it.userType = if (model.member) "1" else "2"
|
it.cardNo = model.cardNo
|
||||||
it.cardNo = model.cardNo
|
|
||||||
}
|
|
||||||
faceList.add(faceEntity)
|
|
||||||
}
|
}
|
||||||
|
faceList.add(faceEntity)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
try {
|
} catch (e: Exception) {
|
||||||
if (faceList.isNotEmpty()) {
|
e.printStackTrace()
|
||||||
FaceDatabase.getInstance(this).faceDao().insert(faceList)
|
}
|
||||||
}
|
try {
|
||||||
recognizeViewModel.refreshFaceList();
|
if (faceList.isNotEmpty()) {
|
||||||
} catch (e: Exception) {
|
FaceDatabase.getInstance(this).faceDao().insert(faceList)
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
}.start()
|
recognizeViewModel.refreshFaceList();
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendFaceData(faceData: String) {
|
private fun sendFaceData(faceData: String) {
|
||||||
@@ -1125,16 +1145,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private var tcpClient: TcpClient? = null
|
private var tcpClient: TcpClient? = null
|
||||||
|
|
||||||
private fun onTakePhotoSuccess(photoUri: Uri) {
|
private suspend fun onTakePhotoSuccess(photoUri: Uri) {
|
||||||
lastPhotoUri = photoUri
|
lastPhotoUri = photoUri
|
||||||
log("registerDataChange main,takePhoto耗时:${System.currentTimeMillis() - startTime}")
|
log("registerDataChange main,takePhoto耗时:${System.currentTimeMillis() - startTime}")
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
log("registerDataChange photoUri = ${photoUri.path}")
|
log("registerDataChange photoUri = ${photoUri.path}")
|
||||||
// viewModel.getIdentifiedFoodList()
|
// viewModel.getIdentifiedFoodList()
|
||||||
lifecycleScope.launch {
|
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
||||||
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
queryFoodData(bitmap)
|
||||||
queryFoodData(bitmap)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,7 +1181,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
log("registerDataChange photoUri 识别数据名称:$foodName")
|
log("registerDataChange photoUri 识别数据名称:$foodName")
|
||||||
runOnUiThread {
|
withContext(Dispatchers.Main) {
|
||||||
binding.flPay.run {
|
binding.flPay.run {
|
||||||
//0-计费,1-不计费
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
@@ -1176,7 +1194,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
//binding.layoutRescan.visibility = View.VISIBLE
|
//binding.layoutRescan.visibility = View.VISIBLE
|
||||||
|
|
||||||
runOnUiThread {
|
withContext(Dispatchers.Main) {
|
||||||
binding.tvToSearch.let {
|
binding.tvToSearch.let {
|
||||||
it.text = "未识别到,手动搜索"
|
it.text = "未识别到,手动搜索"
|
||||||
it.visible()
|
it.visible()
|
||||||
|
|||||||
@@ -118,11 +118,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
collectionAdapter.notifyItemChanged(index)
|
collectionAdapter.notifyItemChanged(index)
|
||||||
}
|
}
|
||||||
// settingActivity?.hideWaitingDialog()
|
// settingActivity?.hideWaitingDialog()
|
||||||
Thread {
|
activity?.lifecycleScope?.launch {
|
||||||
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
||||||
getImageVector(index, bitmap)
|
getImageVector(index, bitmap)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
settingActivity?.hideWaitingDialog()
|
settingActivity?.hideWaitingDialog()
|
||||||
|
|||||||
@@ -1041,6 +1041,7 @@ class MainScreenPresentation(
|
|||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pauseCamera()
|
||||||
step3ShowRecognizeResult(userId)
|
step3ShowRecognizeResult(userId)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1313,6 +1314,7 @@ class MainScreenPresentation(
|
|||||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
||||||
lastFaceTrackId = -1
|
lastFaceTrackId = -1
|
||||||
|
//resumeCamera()
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.d("postUserData userNutritionData是否null: ${userNutrition == null}, currentFood是否null: ${currentFood == null},currentUserId是否null:${currentUserId == null}")
|
.d("postUserData userNutritionData是否null: ${userNutrition == null}, currentFood是否null: ${currentFood == null},currentUserId是否null:${currentUserId == null}")
|
||||||
if (userNutrition == null || currentFood == null || currentUserId == null) {
|
if (userNutrition == null || currentFood == null || currentUserId == null) {
|
||||||
|
|||||||
@@ -87,8 +87,7 @@ object SensorScaleUtils {
|
|||||||
// Thread.sleep(1000)
|
// Thread.sleep(1000)
|
||||||
|
|
||||||
// TODO: 暂时不标定---------
|
// TODO: 暂时不标定---------
|
||||||
//zero()
|
zero()
|
||||||
|
|
||||||
}.start()
|
}.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
|
var currentPageNo = pageNo
|
||||||
|
// Debug log to track current page
|
||||||
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
|
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
|
||||||
|
// Launch a coroutine to perform the face data retrieval
|
||||||
launch {
|
launch {
|
||||||
|
// Set loading state to false
|
||||||
_loadFaceResult.value = false
|
_loadFaceResult.value = false
|
||||||
//获取全量数据时,时间戳改为0
|
//获取全量数据时,时间戳改为0
|
||||||
SpTool.lastFaceTimestamp = 0
|
SpTool.lastFaceTimestamp = 0
|
||||||
val response = repository.getUserFaceCache(currentPageNo)
|
val response = repository.getUserFaceCache(currentPageNo)
|
||||||
if (parseResponse(response)) {
|
val check = parseResponse(response)
|
||||||
// 获取成功一次后缓存状态
|
if (!check) {
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
// 获取失败
|
||||||
withContext(Dispatchers.Default) {
|
onFailure("获取人脸数据失败,${response.msg}(${response.code})")
|
||||||
val list: List<UserFaceModel> = response.data ?: emptyList()
|
return@launch
|
||||||
if (pageNo == 1 && list.isEmpty()) {
|
}
|
||||||
//ToastUtils.showToast("查询人脸数据为空")
|
// 获取成功一次后缓存状态
|
||||||
return@withContext
|
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
||||||
}
|
withContext(Dispatchers.Default) {
|
||||||
//val item = list.map { it.member }
|
val list: List<UserFaceModel> = response.data ?: emptyList()
|
||||||
//Timber.tag(TAG).d("getUserFaceCache item = $item")
|
if (pageNo == 1 && list.isEmpty()) {
|
||||||
val faceEntity = list.map {
|
//ToastUtils.showToast("查询人脸数据为空")
|
||||||
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureStr)).also { item ->
|
onFailure("查询人脸数据为空")
|
||||||
item.userType = if (it.member) "1" else "2"
|
return@withContext
|
||||||
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 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
|
// val nextPageIndex = response.result?.nextPageIndex ?: -1
|
||||||
// if (nextPageIndex > 0) {
|
// if (nextPageIndex > 0) {
|
||||||
// getUserFaceCache(nextPageIndex)
|
// getUserFaceCache(nextPageIndex)
|
||||||
// } else {
|
// } else {
|
||||||
// _loadFaceResult.value = true
|
// _loadFaceResult.value = true
|
||||||
// }
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user