改造objectbox
This commit is contained in:
@@ -6,15 +6,14 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.sw.inbound.objbox.FoodModule
|
import com.sw.inbound.objbox.FoodModule
|
||||||
import com.sw.inbound.sdk.SensorScaleUtils
|
import com.sw.inbound.sdk.SensorScaleUtils
|
||||||
import com.sw.inbound.ui.AppScreen
|
import com.sw.inbound.ui.AppScreen
|
||||||
import com.sw.inbound.utils.ContextUtils
|
|
||||||
import com.sw.inbound.utils.SPUtil
|
|
||||||
import com.sw.inbound.utils.ThreadUtils
|
import com.sw.inbound.utils.ThreadUtils
|
||||||
import com.sw.inbound.viewmodel.ReceiptViewModel
|
import com.sw.inbound.viewmodel.ReceiptViewModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@@ -35,7 +34,9 @@ class MainActivity : ComponentActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
SensorScaleUtils.startScale(autoScale = true)
|
SensorScaleUtils.startScale(autoScale = true)
|
||||||
FoodModule.init(this)
|
lifecycleScope.launch {
|
||||||
|
FoodModule.init(this@MainActivity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
const val PAGE_SIZE = 30
|
const val PAGE_SIZE = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
private var box: Box<Food>? = null
|
// private var box: Box<Food>? = null
|
||||||
private val collectList: MutableList<FoodCollectionBean> = mutableListOf<FoodCollectionBean>()
|
private val collectList: MutableList<FoodCollectionBean> = mutableListOf<FoodCollectionBean>()
|
||||||
private lateinit var binding: ActivityFoodCollectionBinding
|
private lateinit var binding: ActivityFoodCollectionBinding
|
||||||
private lateinit var previewView: PreviewView
|
private lateinit var previewView: PreviewView
|
||||||
@@ -287,11 +287,17 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val cameraCallback: (Uri) -> Unit = { uri ->
|
private val cameraCallback: (Uri) -> Unit = { uri ->
|
||||||
|
lifecycleScope.launch {
|
||||||
|
handlePhoto(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun handlePhoto(uri: Uri) {
|
||||||
val index = collectList.indexOfFirst { it.imageFile == null }
|
val index = collectList.indexOfFirst { it.imageFile == null }
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
toast("每次只允许保存${MAX_COUNT}条数据")
|
toast("每次只允许保存${MAX_COUNT}条数据")
|
||||||
showWaitingDialog2("加载中")
|
showWaitingDialog2("加载中")
|
||||||
rerurn@ cameraCallback
|
return
|
||||||
}
|
}
|
||||||
// toast("index=$index")
|
// toast("index=$index")
|
||||||
try {
|
try {
|
||||||
@@ -373,7 +379,7 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private fun vectorThread() {
|
private fun vectorThread() {
|
||||||
Loading.show(this)
|
Loading.show(this)
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
collectList
|
collectList
|
||||||
//.filter { it.bitmap != null }
|
//.filter { it.bitmap != null }
|
||||||
// .filter { it.imageVector != null }
|
// .filter { it.imageVector != null }
|
||||||
@@ -389,10 +395,10 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
toast("保存成功")
|
toast("保存成功")
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun image2VectorTask(
|
private suspend fun image2VectorTask(
|
||||||
bitmap: Bitmap? = null,
|
bitmap: Bitmap? = null,
|
||||||
imageVector: FloatArray? = null,
|
imageVector: FloatArray? = null,
|
||||||
position: Int
|
position: Int
|
||||||
@@ -408,9 +414,10 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
// }
|
// }
|
||||||
val goods = searchGoodsList[clickIndex]
|
val goods = searchGoodsList[clickIndex]
|
||||||
val saveName = goods.goodsName + goods.goodsCode
|
val saveName = goods.goodsName + goods.goodsCode
|
||||||
ObjectBox.boxStore.runInTx {
|
// ObjectBox.boxStore.runInTx {
|
||||||
box?.put(Food(name = saveName, foodIdx = 0, foodVector = imageVector))
|
// box?.put(Food(name = saveName, foodIdx = 0, foodVector = imageVector))
|
||||||
}
|
// }
|
||||||
|
ObjectBox.put(Food(name = saveName, foodIdx = 0, foodVector = imageVector))
|
||||||
collectList[position].let {
|
collectList[position].let {
|
||||||
// it.imageVector = imageVector
|
// it.imageVector = imageVector
|
||||||
it.isFinish = true
|
it.isFinish = true
|
||||||
@@ -491,9 +498,9 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initBox() {
|
private fun initBox() {
|
||||||
if (box == null) {
|
// if (box == null) {
|
||||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
// box = ObjectBox.boxStore.boxFor(Food::class)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun uploadAllImage() {
|
// private fun uploadAllImage() {
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
var isFirstRecognize = true
|
var isFirstRecognize = true
|
||||||
|
|
||||||
private val takePhotoSuccessCallback: (Uri) -> Unit = { uri ->
|
private val takePhotoSuccessCallback: (Uri) -> Unit = { uri ->
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
searchFood(uri)
|
searchFood(uri)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -307,7 +307,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isShowRecognizeDialog = true
|
var isShowRecognizeDialog = true
|
||||||
private fun searchFood(uri: Uri) {
|
private suspend fun searchFood(uri: Uri) {
|
||||||
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
||||||
val newBmp = BitmapCropper.cropCenter(
|
val newBmp = BitmapCropper.cropCenter(
|
||||||
original = bitmap,
|
original = bitmap,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.sw.inbound.R
|
import com.sw.inbound.R
|
||||||
@@ -14,14 +14,11 @@ import com.sw.inbound.adapter.CollectSearchAdapter
|
|||||||
import com.sw.inbound.databinding.DialogCollectSearchBinding
|
import com.sw.inbound.databinding.DialogCollectSearchBinding
|
||||||
import com.sw.inbound.databinding.LayoutEmptySearchBinding
|
import com.sw.inbound.databinding.LayoutEmptySearchBinding
|
||||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||||
import com.sw.inbound.objbox.Food
|
|
||||||
import com.sw.inbound.objbox.ObjectBox
|
import com.sw.inbound.objbox.ObjectBox
|
||||||
import com.sw.inbound.utils.ext.addOnActionSearchListener
|
import com.sw.inbound.utils.ext.addOnActionSearchListener
|
||||||
import com.sw.inbound.utils.ext.hideKeyboard
|
import com.sw.inbound.utils.ext.hideKeyboard
|
||||||
import com.sw.inbound.utils.ext.toast
|
import com.sw.inbound.utils.ext.toast
|
||||||
import com.sw.inbound.viewmodel.ReceiptViewModel
|
import kotlinx.coroutines.launch
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.boxFor
|
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
class CollectSearchDialog(
|
class CollectSearchDialog(
|
||||||
@@ -69,8 +66,8 @@ class CollectSearchDialog(
|
|||||||
dismiss()
|
dismiss()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
deleteGoods(clickIndex) {
|
showDeleteDialog(clickIndex) {
|
||||||
it.postDelayed({dismiss()}, 500)
|
it.postDelayed({ dismiss() }, 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.rvSearch.let {
|
binding.rvSearch.let {
|
||||||
@@ -142,40 +139,47 @@ class CollectSearchDialog(
|
|||||||
}
|
}
|
||||||
list[position].isSelected = true
|
list[position].isSelected = true
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
deleteGoods(position)
|
showDeleteDialog(position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteGoods(position: Int, deleteAction:()-> Unit = {}) {
|
private fun showDeleteDialog(position: Int, deleteAction: () -> Unit = {}) {
|
||||||
WarnDialog(
|
WarnDialog(
|
||||||
context = context,
|
context = context,
|
||||||
content = "请确认是否删除物品:${list[position].goodsName}?",
|
content = "请确认是否删除物品:${list[position].goodsName}?",
|
||||||
confirmBlock = {
|
confirmBlock = {
|
||||||
Thread {
|
// Thread {
|
||||||
activity?.runOnUiThread {
|
// }.start()
|
||||||
Loading.show(activity!!)
|
activity?.lifecycleScope?.launch {
|
||||||
}
|
deleteGoods(position, deleteAction)
|
||||||
val name = list[position].goodsName
|
}
|
||||||
val filterIdList = box?.all?.filter { it.name == name }?.map { it.id }
|
|
||||||
ObjectBox.boxStore.runInTx {
|
|
||||||
box?.removeByIds(filterIdList)
|
|
||||||
}
|
|
||||||
activity?.runOnUiThread {
|
|
||||||
Loading.dismiss()
|
|
||||||
//list.remove(list[position])
|
|
||||||
//searchAdapter.notifyDataSetChanged()
|
|
||||||
searchAdapter.removeAt(position)
|
|
||||||
activity?.toast("删除成功")
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
loadEmptyView()
|
|
||||||
}
|
|
||||||
deleteAction()
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
}).show()
|
}).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun deleteGoods(position: Int, deleteAction: () -> Unit = {}) {
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
Loading.show(activity!!)
|
||||||
|
}
|
||||||
|
val name = list[position].goodsName ?: ""
|
||||||
|
// val filterIdList = box?.all?.filter { it.name == name }?.map { it.id }
|
||||||
|
// ObjectBox.boxStore.runInTx {
|
||||||
|
// box?.removeByIds(filterIdList)
|
||||||
|
// }
|
||||||
|
ObjectBox.remove(name)
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
Loading.dismiss()
|
||||||
|
//list.remove(list[position])
|
||||||
|
//searchAdapter.notifyDataSetChanged()
|
||||||
|
searchAdapter.removeAt(position)
|
||||||
|
activity?.toast("删除成功")
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
loadEmptyView()
|
||||||
|
}
|
||||||
|
deleteAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun finishRefresh() {
|
private fun finishRefresh() {
|
||||||
binding.refreshLayout.let {
|
binding.refreshLayout.let {
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) {
|
||||||
@@ -186,18 +190,19 @@ class CollectSearchDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var box: Box<Food>? = null
|
// private var box: Box<Food>? = null
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun getCollectGoods(searchName: String? = null) {
|
private fun getCollectGoods(searchName: String? = null) = activity?.lifecycleScope?.launch {
|
||||||
if (box == null) {
|
// if (box == null) {
|
||||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
// box = ObjectBox.boxStore.boxFor(Food::class)
|
||||||
}
|
// }
|
||||||
list.clear()
|
list.clear()
|
||||||
var queryList = box?.all?.distinctBy { it.name }
|
// var queryList = box?.all?.distinctBy { it.name }
|
||||||
if (searchName.isNullOrBlank().not()) {
|
// if (searchName.isNullOrBlank().not()) {
|
||||||
queryList = queryList?.filter { it.name?.contains(searchName!!) == true }
|
// queryList = queryList?.filter { it.name?.contains(searchName!!) == true }
|
||||||
}
|
// }
|
||||||
|
val queryList = ObjectBox.filter(searchName)
|
||||||
queryList?.forEach {
|
queryList?.forEach {
|
||||||
list.add((SearchGoodsInfo.Record(goodsName = it.name)))
|
list.add((SearchGoodsInfo.Record(goodsName = it.name)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,9 @@ import androidx.camera.view.PreviewView
|
|||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import com.sw.inbound.utils.ext.appendText
|
|
||||||
import com.sw.inbound.utils.ext.buildSpannableString
|
|
||||||
import com.sw.inbound.R
|
import com.sw.inbound.R
|
||||||
import com.sw.inbound.activity.GoodsListActivity
|
import com.sw.inbound.activity.GoodsListActivity
|
||||||
import com.sw.inbound.databinding.DialogGoodsStoreBinding
|
import com.sw.inbound.databinding.DialogGoodsStoreBinding
|
||||||
@@ -35,6 +34,8 @@ import com.sw.inbound.utils.BitmapCropper
|
|||||||
import com.sw.inbound.utils.BitmapSaver
|
import com.sw.inbound.utils.BitmapSaver
|
||||||
import com.sw.inbound.utils.CameraUtils
|
import com.sw.inbound.utils.CameraUtils
|
||||||
import com.sw.inbound.utils.ImageUtil
|
import com.sw.inbound.utils.ImageUtil
|
||||||
|
import com.sw.inbound.utils.ext.appendText
|
||||||
|
import com.sw.inbound.utils.ext.buildSpannableString
|
||||||
import com.sw.inbound.utils.ext.dp
|
import com.sw.inbound.utils.ext.dp
|
||||||
import com.sw.inbound.utils.ext.gone
|
import com.sw.inbound.utils.ext.gone
|
||||||
import com.sw.inbound.utils.ext.hideKeyboard
|
import com.sw.inbound.utils.ext.hideKeyboard
|
||||||
@@ -43,11 +44,9 @@ import com.sw.inbound.utils.ext.roundedDecimalPlace
|
|||||||
import com.sw.inbound.utils.ext.toast
|
import com.sw.inbound.utils.ext.toast
|
||||||
import com.sw.inbound.utils.ext.visible
|
import com.sw.inbound.utils.ext.visible
|
||||||
import com.sw.inbound.utils.removeTrailingZeros
|
import com.sw.inbound.utils.removeTrailingZeros
|
||||||
import io.objectbox.Box
|
import kotlinx.coroutines.launch
|
||||||
import io.objectbox.kotlin.boxFor
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.Int
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -441,8 +440,10 @@ class GoodsStoreDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var imageFile: File?=null
|
|
||||||
private var box: Box<Food>? = null
|
private var imageFile: File? = null
|
||||||
|
|
||||||
|
// private var box: Box<Food>? = null
|
||||||
private fun collectGoodsVector() {
|
private fun collectGoodsVector() {
|
||||||
try {
|
try {
|
||||||
ImageUtil.uriToBitmap(context, imageUri!!)?.let { bitmap ->
|
ImageUtil.uriToBitmap(context, imageUri!!)?.let { bitmap ->
|
||||||
@@ -458,21 +459,36 @@ class GoodsStoreDialog(
|
|||||||
)
|
)
|
||||||
imageFile = file
|
imageFile = file
|
||||||
Timber.d("${this.javaClass.simpleName}-collectGoodsVector-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
Timber.d("${this.javaClass.simpleName}-collectGoodsVector-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||||
if (box == null) {
|
// if (box == null) {
|
||||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
// box = ObjectBox.boxStore.boxFor(Food::class)
|
||||||
}
|
// }
|
||||||
Thread {
|
activity?.lifecycleScope?.launch {
|
||||||
try {
|
try {
|
||||||
val imageVector = FoodModule.bitmap2FloatArray(bitmap, true)
|
val imageVector = FoodModule.bitmap2FloatArray(bitmap, true)
|
||||||
if (imageVector != null) {
|
if (imageVector != null) {
|
||||||
ObjectBox.boxStore.runInTx {
|
val food = Food(
|
||||||
box?.put(Food(name = goods.goodsName + goods.goodsCode, foodIdx = 0, foodVector = imageVector))
|
name = goods.goodsName + goods.goodsCode,
|
||||||
}
|
foodIdx = 0,
|
||||||
|
foodVector = imageVector
|
||||||
|
)
|
||||||
|
ObjectBox.put(food)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
|
// Thread {
|
||||||
|
// try {
|
||||||
|
// val imageVector = FoodModule.bitmap2FloatArray(bitmap, true)
|
||||||
|
// if (imageVector != null) {
|
||||||
|
// ObjectBox.boxStore.runInTx {
|
||||||
|
// box?.put(Food(name = goods.goodsName + goods.goodsCode, foodIdx = 0, foodVector = imageVector))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }.start()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|||||||
@@ -47,9 +47,11 @@ object FoodModule {
|
|||||||
suspend fun init(context: Context) {
|
suspend fun init(context: Context) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
module_mobile = Module.load(copyAssetToCache(context, "best_embedding_model_mobile.pt"))
|
module_mobile = Module.load(copyAssetToCache(context, "best_embedding_model_mobile.pt"))
|
||||||
val box = ObjectBox.getBox<Food>()
|
ObjectBox.safeDbOp {
|
||||||
if (box?.all?.isEmpty() == true) {
|
val box = ObjectBox.getBox<Food>()
|
||||||
initDefFoodData(context)
|
if (box?.all?.isEmpty() == true) {
|
||||||
|
initDefFoodData(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,6 +174,21 @@ object ObjectBox {
|
|||||||
getBox<Food>()?.put(entities)
|
getBox<Food>()?.put(entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun filter(name:String?) = safeDbOp {
|
||||||
|
var list = getBox<Food>()?.all?.distinctBy { it.name }
|
||||||
|
if (name.isNullOrBlank().not()) {
|
||||||
|
list?.filter { it.name?.contains(name!!) == true }
|
||||||
|
}
|
||||||
|
list?:emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun remove(name:String) = safeDbOp {
|
||||||
|
getBox<Food>()?.run {
|
||||||
|
val filterIdList = all.filter { it.name == name }.map { it.id }
|
||||||
|
removeByIds(filterIdList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val dbMutex = Mutex() // 协程并发锁,保证写入操作原子性
|
private val dbMutex = Mutex() // 协程并发锁,保证写入操作原子性
|
||||||
private const val DB_DIR_NAME = "objectbox" // ObjectBox 默认数据库目录
|
private const val DB_DIR_NAME = "objectbox" // ObjectBox 默认数据库目录
|
||||||
private const val BACKUP_DIR_NAME = "objectbox_backup" // 备份目录
|
private const val BACKUP_DIR_NAME = "objectbox_backup" // 备份目录
|
||||||
|
|||||||
Reference in New Issue
Block a user