1. Prima di iniziare
Cosa creerai
In questo codelab, creerai un'app per Android utilizzando la libreria FHIR Engine. L'app utilizzerà la libreria FHIR Engine per scaricare le risorse FHIR da un server FHIR e caricare eventuali modifiche locali sul server.
Obiettivi didattici
- Creare un server FHIR locale HAPI utilizzando Docker
- Come integrare la libreria FHIR Engine nella tua applicazione Android
- Utilizzare l'API Sync per configurare un job una tantum o periodico per scaricare e caricare risorse FHIR
- Come utilizzare l'API Search
- Utilizzare le API di accesso ai dati per creare, leggere, aggiornare ed eliminare le risorse FHIR localmente
Che cosa ti serve
- Docker (scarica Docker)
- Una versione recente di Android Studio (v4.1.2 o versioni successive).
- Emulatore Android o un dispositivo Android fisico con Android 7.0 Nougat o versioni successive
- Il codice campione
- Conoscenza di base dello sviluppo Android in Kotlin
Se non hai mai sviluppato app Android, puoi iniziare creando la tua prima app.
2. Configura un server FHIR locale HAPI con dati di test
HAPI FHIR è un popolare server FHIR open source. Nel codelab, utilizziamo un server FHIR locale HAPI a cui connettere l'app per Android.
Configura il server FHIR locale HAPI
- Esegui questo comando in un terminale per ottenere l'immagine più recente di HAPI FHIR
docker pull hapiproject/hapi:latest
- Crea un container FHIR HAPI utilizzando Docker Desktop per eseguire l'immagine precedentemente scaricata
hapiproject/hapi
oppure il comando seguente
Scopri di più.docker run -p 8080:8080 hapiproject/hapi:latest
- Controlla il server aprendo l'URL
http://localhost:8080/
in un browser. Dovresti vedere l'interfaccia web HAPI FHIR.
Compila il server FHIR locale HAPI con i dati di test
Per testare la nostra applicazione, avremo bisogno di alcuni dati di test sul server. Utilizzeremo dati sintetici generati da Synthea.
- Innanzitutto, dobbiamo scaricare i dati di esempio da synthea-samples. Scarica ed estrai i file
synthea_sample_data_fhir_r4_sep2019.zip
. I dati di esempio decompressi contengono numerosi file.json
, ognuno dei quali è un pacchetto di transazioni per un singolo paziente. - Caricheremo i dati dei test per tre pazienti sul server FHIR locale HAPI. Esegui questo comando nella directory contenente i file JSON
curl -X POST -H "Content-Type: application/json" -d @./Aaron697_Brekke496_2fa15bc7-8866-461a-9000-f739e425860a.json http://localhost:8080/fhir/ curl -X POST -H "Content-Type: application/json" -d @./Aaron697_Stiedemann542_41166989-975d-4d17-b9de-17f94cb3eec1.json http://localhost:8080/fhir/ curl -X POST -H "Content-Type: application/json" -d @./Abby752_Kuvalis369_2b083021-e93f-4991-bf49-fd4f20060ef8.json http://localhost:8080/fhir/
- Per caricare sul server i dati dei test per tutti i pazienti, esegui
Tuttavia, il completamento di questa operazione può richiedere molto tempo e non è necessario per il codelab.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done
- Verifica che i dati del test siano disponibili sul server aprendo l'URL
http://localhost:8080/fhir/Patient/
in un browser. Dovresti vedere il testoHTTP 200 OK
e la sezioneResponse Body
della pagina contenente i dati dei pazienti in un bundle FHIR come risultato della ricerca con un conteggiototal
.
3. Configurare l'app per Android
Scarica il codice
Per scaricare il codice per questo codelab, clona il repository dell'SDK FHIR per Android: git clone https://github.com/google/android-fhir.git
Il progetto iniziale per questo codelab si trova in codelabs/engine
.
Importa l'app in Android Studio
Per prima cosa, importa l'app iniziale in Android Studio.
Apri Android Studio, seleziona Import Project (Gradle, Eclipse ADT ecc.) e scegli la cartella codelabs/engine/
dal codice sorgente che hai scaricato in precedenza.
Sincronizza il tuo progetto con i file Gradle
Per praticità, le dipendenze della libreria FHIR Engine sono già state aggiunte al progetto. Ciò ti consente di integrare la libreria FHIR Engine nella tua app. Osserva le seguenti righe fino alla fine del file app/build.gradle.kts
del tuo progetto:
dependencies {
// ...
implementation("com.google.android.fhir:engine:0.1.0-beta05")
}
Per assicurarti che tutte le dipendenze siano disponibili per la tua app, a questo punto devi sincronizzare il progetto con i file Gradle.
Seleziona Sync Project with Gradle Files () dalla barra degli strumenti di Android Studio. Esegui di nuovo l'app per verificare che le dipendenze funzionino correttamente.
Esegui l'app iniziale
Ora che hai importato il progetto in Android Studio, puoi eseguire l'app per la prima volta.
Avvia l'emulatore Android Studio e fai clic su Esegui () nella barra degli strumenti di Android Studio.
4. Crea un'istanza FHIR Engine
Per incorporare il motore FHIR nella tua app per Android, dovrai utilizzare la libreria FHIR Engine e avviare un'istanza del motore FHIR. I passaggi descritti di seguito ti guideranno nella procedura.
- Vai alla classe dell'applicazione, che in questo esempio è
FhirApplication.kt
, che si trova inapp/src/main/java/com/google/android/fhir/codelabs/engine
. - Nel metodo
onCreate()
, aggiungi il seguente codice per inizializzare FHIR Engine:
Note:FhirEngineProvider.init( FhirEngineConfiguration( enableEncryptionIfSupported = true, RECREATE_AT_OPEN, ServerConfiguration( baseUrl = "http://10.0.2.2:8080/fhir/", httpLogger = HttpLogger( HttpLogger.Configuration( if (BuildConfig.DEBUG) HttpLogger.Level.BODY else HttpLogger.Level.BASIC, ), ) { Log.d("App-HttpLog", it) }, ), ), )
enableEncryptionIfSupported
: attiva la crittografia dei dati, se il dispositivo la supporta.RECREATE_AT_OPEN
: determina la strategia di errore del database. In questo caso, ricrea il database se si verifica un errore all'apertura.baseUrl
inServerConfiguration
: si tratta dell'URL di base del server FHIR. L'indirizzo IP fornito10.0.2.2
è riservato appositamente per localhost, accessibile dall'emulatore Android. Scopri di più.
- Nella classe
FhirApplication
, aggiungi la riga seguente per creare lentamente un'istanza del motore FHIR:
Ciò garantisce che l'istanza di FhirEngine venga creata solo al primo accesso, non immediatamente all'avvio dell'app.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) }
- Aggiungi il seguente metodo pratico nella classe
FhirApplication
per facilitare l'accesso da tutta l'applicazione:
Questo metodo statico consente di recuperare l'istanza di FHIR Engine da qualsiasi punto dell'app utilizzando il contesto.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Sincronizza i dati con il server FHIR
- Crea un nuovo corso (
DownloadWorkManagerImpl.kt
). In questa classe, definirai il modo in cui l'applicazione recupera la risorsa successiva dall'elenco da scaricare.
Questa classe ha una coda di tipi di risorse che vuole scaricare. Elabora le risposte ed estrae le risorse dal bundle restituito, che vengono salvate nel database locale.class DownloadWorkManagerImpl : DownloadWorkManager { private val urls = LinkedList(listOf("Patient")) override suspend fun getNextRequest(): DownloadRequest? { val url = urls.poll() ?: return null return DownloadRequest.of(url) } override suspend fun getSummaryRequestUrls() = mapOf<ResourceType, String>() override suspend fun processResponse(response: Resource): Collection<Resource> { var bundleCollection: Collection<Resource> = mutableListOf() if (response is Bundle && response.type == Bundle.BundleType.SEARCHSET) { bundleCollection = response.entry.map { it.resource } } return bundleCollection } }
- Crea una nuova classe
AppFhirSyncWorker.kt
Questa classe definisce la modalità di sincronizzazione dell'app con il server FHIR remoto utilizzando un worker in background.
Qui abbiamo definito la gestione dei download, il resolver dei conflitti e l'istanza del motore FHIR da utilizzare per la sincronizzazione.class AppFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) : FhirSyncWorker(appContext, workerParams) { override fun getDownloadWorkManager() = DownloadWorkManagerImpl() override fun getConflictResolver() = AcceptLocalConflictResolver override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) }
- Nel ViewModel,
PatientListViewModel.kt
, configurerai un meccanismo di sincronizzazione una tantum. Individua e aggiungi questo codice alla funzionetriggerOneTimeSync()
:
Questa coroutine avvia una sincronizzazione una tantum con il server FHIR utilizzando l'AppFhirSyncWorker definito in precedenza. Quindi, aggiornerà l'interfaccia utente in base allo stato del processo di sincronizzazione.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } }
- Nel file
PatientListFragment.kt
, aggiorna il corpo della funzionehandleSyncJobStatus
:
In questo caso, al termine del processo di sincronizzazione, verrà visualizzato un messaggio toast che informa l'utente e l'app mostrerà tutti i pazienti richiamando una ricerca con un nome vuoto.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Ora che hai configurato tutto, esegui l'app. Fai clic sul pulsante Sync
nel menu. Se tutto funziona correttamente, dovresti visualizzare i pazienti del server FHIR locale che vengono scaricati e visualizzati nell'applicazione.
6. Modifica e carica i dati dei pazienti
In questa sezione, ti guideremo nella procedura di modifica dei dati dei pazienti in base a criteri specifici e del caricamento dei dati aggiornati sul server FHIR. Nello specifico, cambieremo le città degli indirizzi con i pazienti che risiedono in Wakefield
e Taunton
.
Passaggio 1: configura la logica di modifica in PatientListViewModel
Il codice in questa sezione viene aggiunto alla funzione triggerUpdate
in PatientListViewModel
- Accedi al motore FHIR:inizia ottenendo un riferimento al motore FHIR nel
PatientListViewModel.kt
.
Questo codice avvia una coroutine nell'ambito del ViewModel e inizializza il motore FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication())
- Cerca pazienti da Wakefield:utilizza il motore FHIR per cercare i pazienti con indirizzo di città
Wakefield
.
Qui stiamo utilizzando il metodoval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }
search
del motore FHIR per filtrare i pazienti in base alla città indirizzo. Il risultato sarà un elenco di pazienti di Wakefield. - Cerca pazienti di Taunton:allo stesso modo, cerca pazienti con indirizzo di città
Taunton
.
Ora abbiamo due elenchi di pazienti: uno di Wakefield e l'altro di Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) }
- Modifica gli indirizzi dei pazienti:esamina ciascun paziente nell'elenco
patientsFromWakefield
, modifica la città inTaunton
e aggiornali nel motore FHIR.
Allo stesso modo, aggiorna ciascun paziente nell'elencopatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }
patientsFromTaunton
in modo che la sua città venga modificata inWakefield
.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) }
- Avvia sincronizzazione:dopo aver modificato i dati localmente, attiva una sincronizzazione una tantum per assicurarti che i dati vengano aggiornati sul server FHIR.
La parentesi graffa di chiusuratriggerOneTimeSync() }
}
indica la fine della coroutine lanciata all'inizio.
Passaggio 2. Testa la funzionalità
- Test dell'interfaccia utente:esegui l'app. Fai clic sul pulsante
Update
nel menu. Dovresti vedere le città degli indirizzi per i pazientiAaron697
eAbby752
scambiati. - Verifica del server. Apri un browser e vai a
http://localhost:8080/fhir/Patient/
. Verifica che la città dell'indirizzo per i pazientiAaron697
eAbby752
sia aggiornata sul server FHIR locale.
Segui questi passaggi per implementare un meccanismo per modificare i dati dei pazienti e sincronizzare le modifiche con il server FHIR.
7. Cerca pazienti per nome
La ricerca dei pazienti per nome può offrire un modo facile da usare per recuperare le informazioni. Qui ti guideremo nella procedura di implementazione di questa funzionalità nella tua richiesta.
Passaggio 1: aggiorna la firma della funzione
Accedi al file PatientListViewModel.kt
e trova la funzione denominata searchPatientsByName
. Aggiungeremo il codice a questa funzione.
Per filtrare i risultati in base alla query sul nome fornita e inviare i risultati per l'aggiornamento dell'interfaccia utente, incorpora il seguente blocco di codice condizionale:
viewModelScope.launch {
val fhirEngine = FhirApplication.fhirEngine(getApplication())
if (nameQuery.isNotEmpty()) {
val searchResult = fhirEngine.search<Patient> {
filter(
Patient.NAME,
{
modifier = StringFilterModifier.CONTAINS
value = nameQuery
},
)
}
liveSearchedPatients.value = searchResult.map { it.resource }
}
}
In questo caso, se il campo nameQuery
non è vuoto, la funzione di ricerca filtrerà i risultati in modo da includere solo i pazienti i cui nomi contengono la query specificata.
Passaggio 2. Testa la nuova funzionalità di ricerca
- Riavvia l'app:dopo aver apportato queste modifiche, ricrea ed esegui l'app.
- Cercare i pazienti: nella schermata dell'elenco dei pazienti, utilizza la funzionalità di ricerca. Ora dovresti essere in grado di inserire un nome (o parte di un nome) per filtrare l'elenco dei pazienti di conseguenza.
Una volta completati questi passaggi, hai migliorato la tua applicazione offrendo agli utenti la possibilità di cercare in modo efficiente i pazienti per nome. Ciò può migliorare notevolmente l'esperienza utente e l'efficienza nel recupero dei dati.
8. Complimenti!
Hai utilizzato la libreria FHIR Engine per gestire le risorse FHIR nella tua app:
- Utilizza l'API Sync per sincronizzare le risorse FHIR con un server FHIR
- Utilizza l'API Data Access per creare, leggere, aggiornare ed eliminare le risorse FHIR locali
- usa l'API Search per cercare risorse FHIR locali
Argomenti trattati
- Come configurare un server FHIR locale HAPI
- Come caricare i dati di test sul server FHIR locale HAPI
- Come creare un'app per Android utilizzando la libreria FHIR Engine
- Come utilizzare l'API Sync, l'API Data Access e l'API Search nella libreria FHIR Engine
Passaggi successivi
- Esplora la documentazione per la libreria FHIR Engine
- Esplora le funzionalità avanzate dell'API Search
- Applica la libreria FHIR Engine nella tua app per Android