简体   繁体   中英

Do I have to use LiveData to read Query from Room DataBase in Android - Kotlin

I develop a simple grocery list App using MVVM model.

I have those files:

  • Database (2 Tables: Shopping Item and Reference Item) + DAO (unique)
  • Repository (Unique)
  • ViewModel (Unique)
  • Fragment / Activity

In the DAO , I define all my queries. Currently, all my //Custom queries return a LiveData<> type like this:

@Dao
interface ShoppingDao {

    // Shopping Items
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertShoppingItem(item: ShoppingItem)

    @Delete
    suspend fun deleteShoppingItem(item: ShoppingItem)

    @Update
    suspend fun updateShoppingItem(item: ShoppingItem)

    @Query(value = "DELETE FROM shopping_items")
    suspend fun deleteAllShoppingItems()

    @Query(value = "SELECT * FROM shopping_items")
    fun getAllShoppingItem(): LiveData<List<ShoppingItem>>

    // Custom
    @Query(value = "SELECT COALESCE(SUM(item_amount),0) FROM shopping_items")
    fun getAllShoppingCount(): LiveData<Int>

    @Query(value = "SELECT COALESCE(SUM(item_total_price), 0.0) FROM shopping_items")
    fun getAllShoppingTotal(): LiveData<Float>

Then in the repository none of them use suspend fun to be called. Thus, in the ViewModel they also don't use a suspend fun to be called.

I would like to use getAllShoppingCount() for example without using a LiveData with an Observer .

Is it possible?

Is it a best practice?

Without the LiveData, I will have to use suspend fun to do my Query , but when I use:

fun updateShoppingItem(item: ShoppingItem) = CoroutineScope(Dispatchers.Main).launch {
    repository.updateShoppingItem(item)
}

It returns a Job not the type the Query should return. How can I change that if I can use something else than LiveData .

My thoughts:

  1. There is no restriction "you have to use LiveData in Room". There is "you can use LiveData" ( link to documentation ). As well as you can use another techniques implementing pattern Observer - RxJava , Coroutines Flow . You can use on of these mechanism to achieve reactive flow in your data - something changes in local DB, your Fragment/Activity will observe that change instantly.
  2. There is no restriction "you shouldn't use LiveData in Room". In mentioned article it was just an answer - "If you don't want use LiveData - well, then you shouldn't use it". May be, there is some trend to replace LiveData in Kotlin with Coroutines Flow, but it's not demanding now.
  3. You can use asynchronous Coroutines as well . In that case you'll not observe changes in your db. In your viewModel you call your suspend-function easier with the help of KTX extension

    viewModelScope.launch(Dispatchers.IO) { repository.updateShoppingItem(item) }

  4. But what exactly use, there are too many "you can use this" and "you can use that"? Well, as usual - it depends, and there is no single best-method, and there are lot of "if". If you don't need to observe changes in your data on-line and you use Kotlin and you're familiar with coroutines - you can use them. If you use Java in that case and you're not familiar with RxJava and you don't want to study it (still why?) you have to bother to manually move all your code working with db into another Thread. If you a RxJava fan - you can use it even if you use Kotlin. If you a RxJava fan but you want to be on the edge of trends - you can use Flow.

Hope this will help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM