es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Android, MVVM: llamar a ContentResolver en el ViewModel

Actualmente, estoy refactorizando la estructura de mi código al patrón de diseño MVVM.

En la documentación oficial de android.com (), escriben lo siguiente:

Cuidado: un ViewModel nunca debe hacer referencia a una vista, Lifecycle o cualquier clase que pueda contener una referencia al contexto de la actividad.

El problema es que en mi código actual estoy usando ContentResolver para consultar la base de datos de contactos en el teléfono.

var cursor: Cursor? = mainActivity.contentResolver.query(
ContactsContract.Data.CONTENT_URI,
projection,
selection,
selectionArgs,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
)

Quiero consultar la base de datos en el código del viewModel, pero parece que ViewModel no tiene ningún método getContentResolver() o algo similar y no se me permite pasar la actividad al viewModel. ¿Cómo puedo acceder a la base de datos desde el viewModel? ¿Es posible hacerlo?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La documentación oficial de Android recomienda fuertemente que ViewModel nunca haga referencia a una vista, ciclo de vida o cualquier clase que pueda contener una referencia al contexto de la actividad. Esto puede crear fugas de memoria y causar problemas de rendimiento. Por lo tanto, no es posible acceder directamente a la base de datos desde el ViewModel.

    Sin embargo, existen formas de acceder indirectamente a la base de datos desde el ViewModel. Una manera es utilizar repositorios que sirvan como una capa de abstracción entre la base de datos y el ViewModel. El repositorio es el responsable de manejar todas las operaciones de la base de datos y devuelve los datos al ViewModel.

    En este caso, puedes crear una clase de repositorio que tenga el método getContentResolver() y que maneje las consultas de la base de datos. El ViewModel puede entonces llamar al método del repositorio para obtener los datos.

    A continuación, se muestra un ejemplo de implementación de la clase de repositorio:

    class ContactsRepository(private val contentResolver: ContentResolver) {
    
        fun getContacts(): List<contact> {
            val contacts = mutableListOf<contact>()
    
            val cursor: Cursor? = contentResolver.query(
                ContactsContract.Data.CONTENT_URI,
                projection,
                selection,
                selectionArgs,
                ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
            )
    
            cursor?.use {
                while (it.moveToNext()) {
                    // parse data and add to contact list
                }
            }
    
            return contacts
        }
    }
    

    En el código anterior, la clase ContactsRepository toma el ContentResolver como un parámetro de constructor y proporciona un método getContacts() para consultar la base de datos y devolver la lista de contactos.

    Luego, en la clase ViewModel, puedes usar el repositorio para obtener los datos:

    class ContactsViewModel(application: Application) : AndroidViewModel(application) {
    
        private val repository = ContactsRepository(application.contentResolver)
    
        fun getContacts(): List<contact> {
            return repository.getContacts()
        }
    }
    

    En el ContactsViewModel, creas una instancia de ContactsRepository y le pasas el ContentResolver del contexto de Application. Luego, en el método getContacts(), llamas al método del repositorio para obtener los datos.

    Al utilizar el patrón de repositorio, puedes mantener el ViewModel limpio y separado de los detalles de implementación de la base de datos mientras aún puedes acceder a los datos.

Comments are closed.