我面临的问题是数据插入表中没有问题,但我无法在任何地方获取它们。我尝试执行打印语句,但只有按顺序存储库中的获取仍然保留数据广告启动效果。
这是我的 Dao 函数,用于创建查询和返回类型并处理插入
DAO
@Dao
interface OrderDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrder(order: Order)
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertProduct(product: Product)
@Query("SELECT * FROM orders")
suspend fun getAllOrders(): List<Order>
@Query("SELECT * FROM products WHERE orderId = :orderId")
suspend fun getProductsForOrder(orderId: String): List<Product>
@Update
suspend fun updateProduct(product: Product)
@Query("UPDATE products SET currentCount = :newCount WHERE productId = :productId AND orderId = :orderId")
suspend fun updateProductCount(productId: String, orderId: String, newCount: String)
@Query("SELECT COUNT(*) FROM orders")
suspend fun countOrders(): Int
@Query("SELECT COUNT(*) FROM products")
suspend fun countProducts(): Int
@Query("SELECT * FROM orders")
fun getAllOrdersAsLiveData(): LiveData<List<Order>>
}
这是订单存储库
我知道实时数据会自动在主线程上,但我不想为此使用主线程
class OrderRepository(private val db: AppDatabase) {
val allOrders: LiveData<List<Order>> = db.orderDao().getAllOrdersAsLiveData()
// Insert an order
@WorkerThread
suspend fun insertOrder(order: Order) {
withContext(Dispatchers.IO) {
try {
db.orderDao().insertOrder(order)
} catch (e: Exception) {
Log.e("OrderRepository", "Error inserting order: ${e.message}")
}
}
}
// Fetch all orders as LiveData
@WorkerThread
fun fetchAllOrdersAsLiveData(): LiveData<List<Order>> {
return db.orderDao().getAllOrdersAsLiveData() // Assuming you have this method in your DAO
}
// Fetch all orders (suspend function)
@WorkerThread
suspend fun fetchAllOrders(): List<Order> {
return withContext(Dispatchers.IO) {
try {
val orders = db.orderDao().getAllOrders()
Log.d("OrderRepository", "Fetched orders: $orders, Size: ${orders.size}")
orders
} catch (e: Exception) {
Log.e("OrderRepository", "Error fetching orders: ${e.message}")
emptyList() // Return an empty list on error
}
}
}
// Insert a product
@WorkerThread
suspend fun insertProduct(product: Product) {
withContext(Dispatchers.IO) {
try {
db.orderDao().insertProduct(product)
} catch (e: Exception) {
Log.e("OrderRepository", "Error inserting product: ${e.message}")
}
}
}
// Update product count
@WorkerThread
suspend fun updateProductCount(productId: String, orderId: String, newCount: String) {
withContext(Dispatchers.IO) {
try {
db.orderDao().updateProductCount(productId, orderId, newCount)
} catch (e: Exception) {
Log.e("OrderRepository", "Error updating product count: ${e.message}")
}
}
}
}
查看模型
class OrderViewModel(private val repository: OrderRepository) : ViewModel() {
val allOrders: LiveData<List<Order>> = repository.allOrders
fun insertOrder(order: Order) {
viewModelScope.launch {
repository.insertOrder(order)
}
}
suspend fun fetchAllOrders(): List<Order> {
return repository.fetchAllOrders()
}
fun insertProduct(product: Product) {
viewModelScope.launch {
repository.insertProduct(product)
}
}
fun updateProductCount(productId: String, orderId: String, newCount: String) {
viewModelScope.launch {
repository.updateProductCount(productId, orderId, newCount)
}
}
}
填充数据库 我知道这可能不是处理这个问题的最有效方法。
private suspend fun parseQrCodes(qrCodeResults: List<String>) {
for (qrCodeResult in qrCodeResults) {
val parts = qrCodeResult.split("%")
val orderNumber = parts[0]
val data: HashMap<String, HashMap<String, String>> = HashMap()
// Insert the order into the database
orderRepository.insertOrder(Order(orderNumber))
for (order in parts.subList(1, parts.size)) {
val (productId, quantity) = order.split("$")
val orderDetails: HashMap<String, String> = HashMap()
orderDetails[quantity] = "0"
data[productId] = orderDetails
// Create a Product object and insert it into the database
val product = Product(productId, orderNumber, quantity)
orderRepository.insertProduct(product) // Call to insertProduct in OrderRepository
}
qrCodesOrderDataParsed[orderNumber] = data
}
}
这是我尝试在另一个活动中访问数据库的方式
// Database and local context initialization
val context = LocalContext.current
val database = AppDatabase.getDatabase(context)
val orderRepository = remember { OrderRepository(database) }
// Create ViewModel
val viewModel: OrderViewModel = viewModel(factory = OrderViewModelFactory(orderRepository))
// Observe the orders LiveData
val dataFromDatabase by viewModel.allOrders.observeAsState(emptyList())
LaunchedEffect(dataFromDatabase){
Log.d("OrderPreviewScreen", "Data from database: $dataFromDatabase")
}
应用程序数据库
@Database(entities = [Order::class, Product::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun orderDao(): OrderDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database"
).build()
INSTANCE = instance
instance
}
}
}
}
实体
@Entity(tableName = "orders")
data class Order(
@PrimaryKey val orderId: String
)
@Entity(tableName = "products")
data class Product(
@PrimaryKey val productId: String,
val orderId: String,
val quantity: String,
var currentCount: String = "0" // Default value
)
查看工厂
class OrderViewModelFactory(private val repository: OrderRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(OrderViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return OrderViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
这是我初始化db的方式
@Composable
fun OrderPreviewScreen(
navController: NavController,
qrCodeResults: List<String> = emptyList(),
) {
// Database and local context initialization
val context = LocalContext.current
val database = AppDatabase.getDatabase(context)
val orderRepository = remember { OrderRepository(database) }
// Create ViewModel
val viewModel: OrderViewModel = viewModel(factory = OrderViewModelFactory(orderRepository))
// Observe the orders LiveData
val dataFromDatabase by viewModel.allOrders.observeAsState(emptyList())
LaunchedEffect(dataFromDatabase) {
Log.d("OrderPreviewScreen", "Data from database: $dataFromDatabase")
}
val orderDataState = remember { mutableStateOf<List<Order>>(emptyList()) }
LaunchedEffect(Unit) {
val orderData_db = viewModel.fetchAllOrders()
// val productData_db = viewModel.fetchAllProducts()
Log.d("OrderPreviewScreen", "Fetched orders Launch Effect : $orderData_db")
// You can use orderData as needed here
orderDataState.value = orderData_db
}
val orderData_db = orderDataState.value
// val productData_db =
Log.d("OrderPreviewScreen", "Fetched orders: $orderData_db")
Room
支持LiveData
,这意味着每当你更新表时,Room
都会通过LiveData
通知更改,这样你就不必再次调用Dao函数来获取最新数据。
当 LiveData.observeAsState()
更新时,
LiveData
会通知 Compose 重新组合。
这将是您唯一需要的部分。
@Composable
fun OrderPreviewScreen(
navController: NavController,
qrCodeResults: List<String> = emptyList(),
) {
// Database and local context initialization
val context = LocalContext.current
val database = AppDatabase.getDatabase(context)
val orderRepository = remember { OrderRepository(database) }
// Create ViewModel
val viewModel: OrderViewModel = viewModel(factory = OrderViewModelFactory(orderRepository))
// Observe the orders LiveData
val dataFromDatabase by viewModel.allOrders.observeAsState(emptyList())
// use dataFromDatabase in your UI
}
我不知道为什么要在另一个变量中再次单独获取数据并使其成为
State
。
此外,您也不需要将
CoroutineScope
切换为 Room
挂起功能,因为房间内部无论如何都会使用 withContext(Dispatchers.IO)
。