Room Dao LiveData как тип возврата, вызывающий ошибку времени компиляции - PullRequest
0 голосов
/ 07 февраля 2019

Я использую Комната и реализовал Дао , который возвращает LiveData.Он работал нормально с добавленной ниже зависимостью.

implementation "androidx.room:room-runtime:2.1.0-alpha04"
kapt "androidx.room:room-compiler:2.1.0-alpha04"

Но когда я добавил новую зависимость от сопрограмм Room, как упомянуто ниже.

implementation "androidx.room:room-runtime:2.1.0-alpha04"
implementation "androidx.room:room-coroutines:2.1.0-alpha04"
kapt "androidx.room:room-compiler:2.1.0-alpha04"

Ниже приведен код, который компилирует

@Dao
interface AccountDao{

    @Query("SELECT * FROM account_master")
    suspend fun getAllAccounts(): List<Account>
}

Ниже приведен код, который выдает ошибку.

@Dao
interface AccountDao{

    @Query("SELECT * FROM account_master")
    suspend fun getAllAccounts(): LiveData<List<Account>>
}

начал получать ошибку.

PlayGround/app/build/tmp/kapt3/stubs/debug/com/playground/www/x/datasource/dao/AccountDao.java:11: error: Not sure how to convert a Cursor to this method's return type (androidx.lifecycle.LiveData<java.util.List<com.playground.www.x.datasource.entity.Account>>).
public abstract java.lang.Object getAllAccounts(@org.jetbrains.annotations.NotNull()

Кто-нибудь сталкивался с подобной проблемой?

Ответы [ 3 ]

0 голосов
/ 30 апреля 2019

Я думаю, что решение на самом деле состоит в том, чтобы просто вернуть LiveData без использования Coroutines .LiveData работает из коробки, нет причин использовать Coroutines при возврате LiveData.

При использовании LiveData он уже обрабатывает его в фоновом потоке.Если НЕ используется LiveData, то в этом случае вы можете использовать сопрограммы (и, возможно, в конечном итоге каналы сопрограмм) или RxJava2.

См. Этот кодовый ярлык для примера: https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin. Здесь им нужен фоновый поток для вставок, ноне для возвращенных LiveData.

Примечание: в реальной кодовой метке, похоже, есть ошибка, когда DAO не возвращает LiveData.Я исправил это в примере ниже.

@Dao
interface WordDao {

    @Query("SELECT * from word_table ORDER BY word ASC")
    fun getAllWords(): LiveData<List<Word>>

    @Insert
    suspend fun insert(word: Word)

    @Query("DELETE FROM word_table")
    fun deleteAll()
}

class WordRepository(private val wordDao: WordDao) {

    val allWords: LiveData<List<Word>> = wordDao.getAllWords()

    @WorkerThread
    suspend fun insert(word: Word) {
        wordDao.insert(word)
    }
}
0 голосов
/ 24 августа 2019

Как отметил Майкл Весково, есть два возможных способа выполнения асинхронного вызова:

@Dao
interface AccountDao{
    @Query("SELECT * FROM account_master")
    suspend fun getAllAccounts(): List<Account>
}

@Dao
interface AccountDao{
    @Query("SELECT * FROM account_master")
    fun getAllAccounts(): LiveData<List<Account>>
}

Какой из них вы будете использовать, зависит от вашего варианта использования.Например, я бы использовал первый, если мой потребитель DAO (обычно репозиторий) будет создавать LiveData для модели (в случае, если мне не нужно наблюдать изменения из локальной БД).

Если мне нужно наблюдать за изменениями в локальной БД (например, какой-то другой сервис может обновлять БД за это время), я бы использовал второй.

0 голосов
/ 07 февраля 2019

Текущая реализация Room не поддерживает сопрограмм с LiveData.В качестве обходного пути вы можете реализовать его следующим образом:

@Dao
interface AccountDao{

@Query("SELECT * FROM account_master")
    suspend fun getAllAccounts(): List<Account>
}

И в вашей реализации класса ViewModel вы можете создать LiveData и присвоить ему значение, полученное из БД:

class MainViewModel : ViewModel() {
    private val dao: AccountDao = ...// initialize it somehow
    private var job: Job = Job()
    private val scope = CoroutineScope(job + Dispatchers.Main)
    lateinit var accounts: MutableLiveData<List<Account>>

    override fun onCleared() {
        super.onCleared()
        job.cancel()
    }

    fun getAccounts(): LiveData<List<Account>> {
        if (!::accounts.isInitialized) {
            accounts = MutableLiveData()

            scope.launch {
                accounts.postValue(dao.getAllAccounts())
            }

        }
        return accounts
    }
}

Для использования Dispatchers.Main import:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
...