Estoy usando Room e implementé Dao que devuelve LiveData . Estaba funcionando bien con la dependencia a continuación agregada.
implementation "androidx.room:room-runtime:2.1.0-alpha04" kapt "androidx.room:room-compiler:2.1.0-alpha04"Pero cuando agregué una nueva dependencia de corrutina Room como se menciona a continuación.
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"A continuación se muestra el código que compila
@Dao interface AccountDao{ @Query("SELECT * FROM account_master") suspend fun getAllAccounts(): List<Account> }A continuación se muestra el código que da error.
@Dao interface AccountDao{ @Query("SELECT * FROM account_master") suspend fun getAllAccounts(): LiveData<List<Account>> }comenzó a recibir el error.
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()¿Alguien enfrenta un problema similar?
Creo que la solución aquí es simplemente devolver LiveData sin usar Coroutines . LiveData funciona de forma inmediata, no hay razón para usar Coroutines al devolver LiveData.
Cuando usa LiveData, ya lo maneja en un hilo de fondo. Cuando NO use LiveData, en ese caso puede usar Coroutines (y tal vez eventualmente Coroutines Channels) o RxJava2.
Consulte este codelab para ver un ejemplo: https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin . Aquí necesitan un subproceso de fondo para las inserciones, pero no para los LiveData devueltos.
Nota: parece haber un error en el laboratorio de código real donde el DAO no devuelve un LiveData. Lo he corregido en el ejemplo a continuación.
@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) } }Eliminar la función de suspensión. LiveData ya es asíncrono. No hay necesidad de una función de suspensión.
@Dao interface AccountDao{ @Query("SELECT * FROM account_master") fun getAllAccounts(): LiveData<List<Account>> }La implementación actual de Room no admite LiveData ( no podemos definir una función para suspend y devolver LiveData al mismo tiempo). Como solución alternativa, puede implementarlo de la siguiente manera:
@Dao interface AccountDao { @Query("SELECT * FROM account_master") suspend fun getAllAccounts(): List<Account> } class AccountRepository(private val dao: AccountDao) { suspend fun getAccounts(): List<Account> { return dao.getAllAccounts() } } Y en su implementación de la clase ViewModel , puede crear un objeto LiveData y asignarle un valor, recuperado de la base de datos:
class MainViewModel(private val accountRepository: AccountRepository) : ViewModel() { private val _accounts: MutableLiveData<List<Account>> val accounts = _accounts // To access it from Activity/Fragment fun loadAccounts() { viewModelScope.launch { accounts.value = accountRepository.getAccounts() } } } Para utilizar la importación Dispatchers.Main :
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1' O puede devolver LiveData directamente sin marcar la función como suspend :
@Dao interface AccountDao { @Query("SELECT * FROM account_master") fun getAllAccounts(): LiveData<List<Account>> } class AccountRepository(private val dao: AccountDao) { fun getAccounts(): LiveData<List<Account>> { return dao.getAllAccounts() } } class MainViewModel(private val accountRepository: AccountRepository) : ViewModel() { val accounts = accountRepository.getAccounts() }