来自 room kotlin 的数据仅出现在 Launcheffects 中,而不出现在其他地方

问题描述 投票:0回答:1

我面临的问题是数据插入表中没有问题,但我无法在任何地方获取它们。我尝试执行打印语句,但只有按顺序存储库中的获取仍然保留数据广告启动效果。

这是我的 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")
android database kotlin mobile android-jetpack-compose
1个回答
0
投票

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)

© www.soinside.com 2019 - 2024. All rights reserved.