Modules and repositories¶
El objeto D2 es el punto de entrada para interactuar con el SDK. El SDK obliga al objeto D2 a ser un singleton en toda la aplicación.
Los módulos son la capa debajo de D2. Actúan como un contenedor para la funcionalidad relacionada. Un módulo incluye algunos repositorios relacionados y puede exponer algunos servicios y helpers.
Los repositorios actúan como una fachada para la base de datos (o API web en algunos casos). Ofrecen capacidades de lectura de metadatos y lectura/escritura de datos.
Dealing with return types¶
Most of the actions in the SDK are time consuming and must be executed in a secondary thread. To make that explicit, and to notify about the progress of long operations such as metadata or data sync, every asynchronous method is exposed in three flavours:
| Prefix | Return type | Notes |
|---|---|---|
suspend | the value itself | Kotlin suspend function. Recommended, and used in the examples throughout this guide. |
rx | RxJava (Single, Completable, Observable, Flowable) | For apps already built around RxJava. |
blocking | the value itself | Must not be called from the main thread. |
Operations that report progress (metadata and data download, data upload, reserved value download) do not have a suspend variant, because a single return value cannot convey progress. They expose a flow variant instead, which returns a Flow<D2Progress>: flowDownload(), flowUpload(), flowDownloadReservedValues().
// Coroutines
val programs = d2.programModule().programs().suspendGet()
// RxJava
d2.programModule().programs()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.rxGet()
.subscribe { programs -> } // List<Program>
// Blocking, from a background thread
val programs = d2.programModule().programs().blockingGet()
Important
Unprefixed RxJava methods are deprecated in favour of their
rxcounterparts, so that the coroutine variants can coexist with them. The old names still work, but they will be removed in a future release.The table below lists the drop-in replacement, which keeps the RxJava return type. When migrating, consider moving to the
suspendvariant instead.
Deprecated Drop-in replacement get()rxGet()count()rxCount()isEmpty()rxIsEmpty()getUids()rxGetUids()exists()rxExists()add(o)rxAdd(o)set(value)rxSet(value)delete()/deleteIfExist()rxDelete()/rxDeleteIfExist()download()rxDownload()upload()rxUpload()evaluate()rxEvaluate()The same rename applies to most module and service methods (
logIn(),logOut(),isLogged(),checkServerUrl(),validate(), theEventServiceandEnrollmentServicemethods, the reserved value manager, ...): the replacement is the same name prefixed withrx, and asuspendvariant is available as well.D2Manager.instantiateD2()follows the same pattern, replaced byD2Manager.rxInstantiateD2().Independently of that rename,
getPaged(int)is also deprecated, replaced bygetPagingData(int), which returns aFlow<PagingData<M>>instead of aLiveData<PagedList<M>>.
Acceder a la base de datos requiere mucho tiempo y se recomienda hacerlo en un subproceso separado usando cualquiera de los métodos recomendados. Sin embargo, los procedimientos que implican el acceso a la API web, como el inicio de sesión, los metadatos o la descarga o carga de datos deben ejecutarse en un subproceso separado, de lo contrario, Android arrojará un error.
Construcción de consultas¶
Repositories offer a builder syntax with compile-time validation to access the resources. A typical query is composed of some modifiers (filter, order, nested fields) and ends with an action (suspendGet/rxGet/blockingGet, suspendCount/rxCount/blockingCount, getPagingData,...).
// Generic syntax
d2.<module>.<repository>
.[ filter | orderBy | nested fields ]
.<action>
// An example for events
d2.eventModule().events()
.byOrganisationUnitUid().eq("DiszpKrYNg8")
.byEventDate().after(Date("2019-05-05"))
.orderByEventDate(DESC)
.withTrackedEntityDataValues()
.suspendGet()
Filtros¶
Los repositorios exponen la lista de filtros disponibles precedidos por la palabra clave "by". La lista de operadores de filtro disponibles para cada filtro depende del tipo de valor del filtro: por ejemplo, un tipo de valor Fecha ofrecerá operadores como después, antes, en períodos, mientras que un tipo de valor Booleano oferta isFalse o isTrue.
Common filter operators include: - Equality: eq(), notEq() - Comparison: gt(), lt(), ge(), le() - String matching: like(), notLike() - Collection: in() - matches any value in the provided list - Null checks: isNull(), isNotNull() - Emptiness: isNullOrBlank(), isNotNullAndIsNotBlank() - available in data value filters, where the event query repository exposes them as isEmpty(Boolean)
Varios filtros pueden ser anexados a la misma consulta en cualquier orden. Los filtros se unen globalmente mediante el operador "AND". Esto significa que una consulta como
d2.eventModule().events()
.byOrganisationUnitUid().eq("DiszpKrYNg8")
.byEventDate().after(Date("2019-05-05"))
...
retornará los eventos asignados a la unidad organizativa "DiszpKrYNg8" AND cuya fecha de evento sea posterior a "2019-05-05".
The in() operator is particularly useful for querying multiple values at once:
// Query tracked entity instances with specific data values
d2.trackedEntityModule().trackedEntityInstanceQuery()
.byDataValue("dataElementUid").`in`("value1", "value2", "value3")
.onlineFirst()
.suspendGet()
Ordenar por¶
Los modificadores de orden tienen como prefijo la palabra clave "orderBy".
Varios modificadores "orderBy" pueden ser anexados a la misma consulta. El orden de los modificadores "orderBy" dentro de la consulta determina la prioridad del orden. Esto significa que una consulta como
d2.eventModule().events()
.orderByEventDate(DESC)
.orderByLastUpdated(DESC)
...
ordenará por descendiente EventDate en primer lugar, y luego por descendiente LastUpdated
Incluir campos anidados¶
Los repositorios retornan clases que no coinciden exactamente con las tablas de la base de datos: son objetos más complejos que pueden incluir algunas propiedades obtenidas de otras tablas. Por ejemplo, la clase Event tiene una propiedad llamada trackedEntityDataValues que incluye una lista de TrackedEntityDataValues. La razón principal para elegir este tipo de objetos es absorber la complejidad de tratar con tablas de enlaces para que la aplicación no tenga que preocuparse por construir enlaces entre objetos.
Por cuestiones de rendimiento, este tipo de propiedades no se incluyen por defecto: deben ser consultadas explícitamente. En los repositorios, las propiedades que no están incluidas por defecto y necesitan ser consultadas tienen como prefijo la palabra clave "with".
Varias propiedades pueden ser anexadas en la misma consulta en cualquier orden. Por ejemplo, una consulta como
d2.programModule().programs()
.withTrackedEntityType()
...
retornará un objeto anidado TrackedEntityType.
Helpers¶
El SDK incluye algunos helpers en el paquete org.hisp.dhis.android.core.arch.helpers. Se pueden encontrar fácilmente en Android Studio buscando Helper en los nombres de las clases. Incluyen algunos métodos útiles para realizar operaciones comunes:
AccessHelper: relacionado con el objeto de acceso (configuración de uso compartido).CollectionsHelper: operaciones comunes para colecciones.CoordinateHelper,GeometryHelper: manipulación de datos geoespaciales.FileResizerHelper,FileCompressionHelper,FileResourceDirectoryHelper: file resource manipulation.UidsHelper: operaciones comunes para colecciones de objetos con uid.UserHelper: operaciones relacionadas con la autenticación de usuarios.ValueType: lista de diferentes tipos de valores y sus validadores.
Lista de módulos¶
Módulos del sistema:
- importModule
- maintenanceModule
- systemInfoModule
- settingModule
- dataStoreModule
- wipeModule
Módulos de bloque grande:
- metadataModule
- aggregatedDataModule
Módulos específicos:
- attributeModule
- categoryModule
- constantModule
- dataElementModule
- dataSetModule
- dataValueModule
- enrollmentModule
- eventModule
- fileResourceModule
- indicatorModule
- legendSetModule
- noteModule
- organisationUnitModule
- optionModule
- periodModule
- programModule
- relationshipModule
- smsModule
- trackedEntityModule
- userModule
- validationModule