refactor(utils): 重构 FoodVectorTool 并优化 zero() 提示控制

- 重构 FoodVectorTool:移除单例 pageNum 状态污染问题,分页逻辑下沉为私有 fetchPage,saveFoodVector 改为私有,PAGE_SIZE 移入内部定义,对外统一暴露 loadAndSaveFoodVector 接口
- 更新 InitActivity、MainActivity 调用方,移除重复的 onPageFinish 回调
- SensorScaleUtils.zero() 新增 isShowToastRemind 可选参数,支持按需显示标定成功提示

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-07 09:25:03 +08:00
co-authored by Claude Sonnet 4.6
parent ab0d9b35f5
commit a45690d3be
4 changed files with 76 additions and 73 deletions
@@ -13,10 +13,7 @@ import com.sw.dualscreen.dialog.RemindDialog
import com.sw.dualscreen.ext.clickWithDebounce
import com.sw.dualscreen.ext.invisible
import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.model.response.FoodVector
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.FoodModule
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.utils.FoodVectorTool
import com.sw.dualscreen.utils.L
import com.sw.dualscreen.utils.NetworkUtils
@@ -42,43 +39,11 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
}
private fun getCollectedFoodVector(block: () -> Unit) {
// userViewModel.getCollectedFoodVector(
// param = mutableMapOf(
// "pageNum" to "$pageNum",
// "pageSize" to "$PAGE_SIZE",
// "version" to GlobalData.foodModelVersion
// )
// ) { items ->
// if (items == null) {
// getVectorErrorDialog()
// return@getCollectedFoodVector
// }
// val list = items
// if (pageNum == 1 && list.isEmpty()) {
// block()
// return@getCollectedFoodVector
// }
// if (list.size >= PAGE_SIZE) {
// saveFoodVector(list)
// pageNum++
// getCollectedFoodVector(block)
// return@getCollectedFoodVector
// }
// if (list.isNotEmpty()) {
// saveFoodVector(list)
// block()
// }
// }
FoodVectorTool.getFoodVector(
userViewModel,
onPageFinish = { list ->
list?.let { FoodVectorTool.saveFoodVector(lifecycleScope,list) }
}, successBlock = {
block()
}, failureBlock = {
getVectorErrorDialog()
}
FoodVectorTool.loadAndSaveFoodVector(
userViewModel = userViewModel,
lifecycleScope = lifecycleScope,
successBlock = { block() },
failureBlock = { getVectorErrorDialog() }
)
}
@@ -215,19 +215,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
FaceServer.getInstance().clearAllFaces()
}
withContext(Dispatchers.IO) {
ObjectBox.removeAll()
}
FoodVectorTool.getFoodVector(
FoodVectorTool.loadAndSaveFoodVector(
userViewModel = viewModel,
onPageFinish = { list ->
list?.let { FoodVectorTool.saveFoodVector(lifecycleScope,list) }
},
lifecycleScope = lifecycleScope,
successBlock = {
viewModel.getUserFaceCache(pageNo = 1)
}, failureBlock = {
hideWaitingDialog() // 显示提示信息
},
failureBlock = {
hideWaitingDialog()
ToastUtils.showToast(it)
}
)
@@ -129,13 +129,15 @@ object SensorScaleUtils {
/**
* 零位标定
*/
fun zero() {
fun zero(isShowToastRemind: Boolean = false) {
Timber.d("zero isOpened = $isOpened, mSensorScale = $mSensorScale")
if (!isOpened) return
mSensorScale?.zero {
isZero = true
Timber.d("zero 零位标定操作成功")
ToastUtils.showToast("零位标定操作成功")
if (isShowToastRemind) {
ToastUtils.showToast("零位标定操作成功")
}
}
}
@@ -1,8 +1,7 @@
package com.sw.dualscreen.utils
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.LifecycleCoroutineScope
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.activity.InitActivity
import com.sw.dualscreen.model.response.FoodVector
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.ObjectBox
@@ -10,15 +9,50 @@ import com.sw.dualscreen.viewmodel.UserViewModel
import kotlinx.coroutines.launch
object FoodVectorTool {
var pageNum: Int = 1
const val PAGE_SIZE: Int = InitActivity.PAGE_SIZE
fun getFoodVector(
/** 每页拉取条数 */
private const val PAGE_SIZE = 100
/**
* 统一入口:分页拉取所有食物向量数据并保存到本地 ObjectBox
*
* @param userViewModel 请求 ViewModel
* @param lifecycleScope 协程作用域(用于保存操作)
* @param successBlock 全部数据拉取并保存成功后回调
* @param failureBlock 任意一次请求失败时回调,参数为错误信息
*/
fun loadAndSaveFoodVector(
userViewModel: UserViewModel,
onPageFinish:(List<FoodVector>?)-> Unit,
lifecycleScope: LifecycleCoroutineScope,
successBlock: () -> Unit,
failureBlock: (String) -> Unit
): Unit {
) {
// 每次调用从第 1 页开始,避免单例状态污染
fetchPage(
pageNum = 1,
userViewModel = userViewModel,
lifecycleScope = lifecycleScope,
successBlock = successBlock,
failureBlock = failureBlock
)
}
/**
* 递归分页请求(内部方法,外部不感知分页细节)
*
* @param pageNum 当前页码
* @param userViewModel 请求 ViewModel
* @param lifecycleScope 协程作用域
* @param successBlock 成功回调
* @param failureBlock 失败回调
*/
private fun fetchPage(
pageNum: Int,
userViewModel: UserViewModel,
lifecycleScope: LifecycleCoroutineScope,
successBlock: () -> Unit,
failureBlock: (String) -> Unit
) {
userViewModel.getCollectedFoodVector(
param = mutableMapOf(
"pageNum" to "$pageNum",
@@ -30,30 +64,36 @@ object FoodVectorTool {
failureBlock("未查询到向量数据")
return@getCollectedFoodVector
}
val list = items
if (pageNum == 1 && list.isEmpty()) {
//接口成功无数据,暂时认为成功
// 第一页为空,视为成功(数据库无数据)
if (pageNum == 1 && items.isEmpty()) {
successBlock()
return@getCollectedFoodVector
}
if (list.size >= PAGE_SIZE) {
onPageFinish(list)
pageNum++
getFoodVector(userViewModel, onPageFinish, successBlock, failureBlock)
return@getCollectedFoodVector
// 有数据则保存
if (items.isNotEmpty()) {
saveFoodVector(lifecycleScope, items)
}
if (list.isNotEmpty()) {
onPageFinish(list)
// 数据量达到一页上限,继续拉取下一页
if (items.size >= PAGE_SIZE) {
fetchPage(pageNum + 1, userViewModel, lifecycleScope, successBlock, failureBlock)
} else {
successBlock()
}
successBlock()
}
}
fun saveFoodVector(lifecycleScope: androidx.lifecycle.LifecycleCoroutineScope ,list: List<FoodVector>) {
/**
* 将向量数据列表保存到 ObjectBox 本地数据库
*
* @param lifecycleScope 协程作用域
* @param list 待保存的食物向量数据列表
*/
private fun saveFoodVector(lifecycleScope: LifecycleCoroutineScope, list: List<FoodVector>) {
lifecycleScope.launch {
val vectorList = list.map { vt ->
val foodVector = vt.foodVector?.removeSurrounding("[", "]")?.split(",")
?.map { it.toFloatOrNull() ?: 0.0f }?.toFloatArray()
// 解析向量字符串 "[0.1,0.2,...]" 为 FloatArray
val foodVector = vt.foodVector?.removeSurrounding("[", "]")
?.split(",")?.map { it.toFloatOrNull() ?: 0.0f }?.toFloatArray()
Food(
collectId = vt.id,
foodId = vt.foodId,
@@ -65,5 +105,4 @@ object FoodVectorTool {
ObjectBox.putAll(vectorList)
}
}
}
}