La documentación oficial de Android establece que no se recomienda usar allowMainThreadQueries() porque podría bloquear la interfaz de usuario durante un largo período de tiempo y desencadenar un ANR. Pero las corrutinas de Kotlin nos dieron la posibilidad de realizar alguna operación en el subproceso principal sin bloquear efectivamente la interfaz de usuario.
Entonces pregunto: ¿es seguro usar allowMainThreadQueries() y acceder a la base de datos en un ámbito de rutina que se ejecuta en el hilo principal? Como en lo siguiente:
// WITH allowMainThreadQueries() val activityJob = Job() val mainScope = CoroutineScope(Dispatchers.Main + activityJob) mainscope.launch { // access room database and retrieve some data // update UI with data retrived }¿O deberíamos apegarnos a la forma antigua de no permitir consultas de subprocesos principales y realizar consultas de base de datos en otro subproceso?
// WITHOUT allowMainThreadQueries() val activityJob = Job() val defaultScope = CoroutineScope(Dispatchers.Default + activityJob) val mainScope = CoroutineScope(Dispatchers.Main + activityJob) defaultScope.launch { // access room database and retrieve some data mainScope.launch { // update UI with data retrived } } Lo pregunto por la forma anterior (con allowMainThreadQueries() ):
No debería necesitar allowMainThreadQueries() para que esto funcione. Una corrutina con ámbito se ejecuta en su subproceso.
Esto es lo que hice no hace mucho:
@UiThread fun getUsers(context: Context): LiveData<List<User>> { if (!::users.isInitialized) { users = MutableLiveData() users.postValue(MyDatabase.get(context).users().getAll()) GlobalScope.launch(Dispatchers.Main) { val usersFromDb: List<User> = async(Dispatchers.IO) { return@async MyDatabase.get(context).users().getAll() }.await() users.value = usersFromDb } } return users } Puede ver que se llama a este método getUsers() desde el hilo principal, devolviendo un LiveData (que es útil en este caso). La consulta de la base de datos ocurre en GlobalScope.launch() .
Así que sí, tu diseño es uno que personalmente me gusta. Y uno que funcione. Pero no creo que necesites allowMainThreadQueries() en absoluto. Siéntase libre de leer (mi) publicación de blog: https://proandroiddev.com/android-viewmodel-livedata-coroutines-contraption-e1e44af690a6
Se recomienda acceder a la base de datos en su ViewModel dentro viewmodelScope . Si es así, necesita acceder a la base de datos de la sala desde la actividad o el uso de fragmentos
lifecyclescope.launch{ // access database dao functions here which are suspend in definition. }
O dentro de lifecycleScope, cambie su hilo usando withContext(Dispatchers.IO){}