1. Zanim zaczniesz
Co utworzysz
W ramach tego ćwiczenia w Codelabs utworzysz aplikację na Androida przy użyciu biblioteki FHIR Engine. Aplikacja użyje biblioteki silnika FHIR do pobrania zasobów FHIR z serwera FHIR i przesłania wszelkich lokalnych zmian na serwer.
Czego się nauczysz
- Jak utworzyć lokalny serwer FHIR HAPI przy użyciu Dockera
- Jak zintegrować bibliotekę FHIR silnika z aplikacją na Androida
- Jak za pomocą interfejsu Sync API skonfigurować jednorazowe lub okresowe zadanie pobierania i przesyłania zasobów FHIR
- Jak korzystać z interfejsu Search API
- Jak używać interfejsów API dostępu do danych do lokalnego tworzenia, odczytywania, aktualizowania i usuwania zasobów FHIR
Czego potrzebujesz
- Docker (pobierz Dockera),
- najnowszą wersję Android Studio (4.1.2 lub nowszego),
- Emulator Androida lub fizyczne urządzenie z Androidem w wersji 7.0 Nougat lub nowszej.
- Przykładowy kod
- Podstawowa wiedza o programowaniu na Androida w Kotlin
Jeśli nie masz jeszcze aplikacji na Androida, możesz zacząć od stworzenia pierwszej aplikacji.
2. Skonfiguruj lokalny serwer FHIR HAPI z danymi testowymi
HAPI FHIR to popularny serwer FHIR typu open source. W ramach ćwiczenia w Codelabs używamy lokalnego serwera FHIR HAPI, aby połączyć się z aplikacją na Androida.
Konfigurowanie lokalnego serwera FHIR HAPI
- Uruchom poniższe polecenie w terminalu, aby uzyskać najnowszy obraz FHIR HAPI
docker pull hapiproject/hapi:latest
- Utwórz kontener FHIR HAPI, korzystając z Docker Desktop do uruchomienia wcześniej pobranego obrazu
hapiproject/hapi
lub z następującego polecenia:
Więcej informacjidocker run -p 8080:8080 hapiproject/hapi:latest
- Sprawdź serwer, otwierając adres URL
http://localhost:8080/
w przeglądarce. Powinien wyświetlić się interfejs internetowy HAPI FHIR.
Wypełnij lokalny serwer FHIR HAPI danymi testowymi
Aby przetestować naszą aplikację, potrzebujemy danych testowych na serwerze. Użyjemy danych syntetycznych wygenerowanych przez firmę Synthea.
- Najpierw musimy pobrać przykładowe dane z przykładów syntetycznych. Pobierz i rozpakuj plik
synthea_sample_data_fhir_r4_sep2019.zip
. Rozpakowane przykładowe dane zawierają wiele plików.json
, z których każdy jest pakietem transakcji dla pojedynczego pacjenta. - Prześlemy dane testowe 3 pacjentów na lokalny serwer FHIR HAPI. Uruchom podane niżej polecenie w katalogu zawierającym pliki 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/
- Aby przesłać na serwer dane testowe wszystkich pacjentów, uruchom polecenie
Może to jednak zająć dużo czasu i nie jest konieczne w przypadku ćwiczeń z programowania.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done
- Sprawdź, czy dane testowe są dostępne na serwerze, otwierając adres URL
http://localhost:8080/fhir/Patient/
w przeglądarce. Powinny być widoczne tekstyHTTP 200 OK
i sekcjaResponse Body
na stronie zawierającej dane pacjentów w pakiecie FHIR jako wynik wyszukiwania z liczbątotal
.
3. Konfigurowanie aplikacji na Androida
Pobierz kod
Aby pobrać kod do tego ćwiczenia z programowania, skopiuj repozytorium pakietu SDK FHIR na Androida: git clone https://github.com/google/android-fhir.git
Projekt startowy tego ćwiczenia z programowania znajduje się w regionie codelabs/engine
.
Importowanie aplikacji do Android Studio
Najpierw zaimportujemy aplikację startową do Android Studio.
Otwórz Android Studio, wybierz Importuj projekt (Gradle, Eclipse ADT itp.) i wybierz folder codelabs/engine/
z pobranego wcześniej kodu źródłowego.
Synchronizowanie projektu z plikami Gradle
Dla Twojej wygody zależności biblioteki FHIR zostały już dodane do projektu. Pozwoli Ci to zintegrować bibliotekę silnika FHIR z aplikacją. Zwróć uwagę na te wiersze na końcu pliku app/build.gradle.kts
projektu:
dependencies {
// ...
implementation("com.google.android.fhir:engine:0.1.0-beta05")
}
Aby mieć pewność, że w przypadku aplikacji dostępne są wszystkie zależności, zsynchronizuj projekt z plikami Gradle.
Na pasku narzędzi Android Studio wybierz Sync Project with Gradle Files (Synchronizuj projekt z plikami Gradle) (). Uruchomisz też aplikację jeszcze raz, aby sprawdzić, czy zależności działają prawidłowo.
Uruchom aplikację startową
Po zaimportowaniu projektu do Android Studio możesz uruchomić aplikację po raz pierwszy.
Uruchom emulator Android Studio i na pasku narzędzi Android Studio kliknij Uruchom ().
4. Utwórz instancję silnika FHIR
Aby wdrożyć silnik FHIR w aplikacji na Androida, musisz użyć biblioteki silnika FHIR i zainicjować instancję silnika FHIR. Poniżej znajdziesz informacje o tym, jak to zrobić.
- Przejdź do klasy aplikacji, która w tym przykładzie to
FhirApplication.kt
, w lokalizacjiapp/src/main/java/com/google/android/fhir/codelabs/engine
. - W metodzie
onCreate()
dodaj ten kod, aby zainicjować silnik FHIR:
Uwagi: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
: włącza szyfrowanie danych, jeśli urządzenie obsługuje tę funkcję.RECREATE_AT_OPEN
: określa strategię dotyczącą błędów bazy danych. W takim przypadku, jeśli podczas otwierania wystąpi błąd, odtworzy bazę danych.baseUrl
wServerConfiguration
: to jest podstawowy adres URL serwera FHIR. Podany adres IP10.0.2.2
jest specjalnie zarezerwowany dla hosta lokalnego i można uzyskać do niego dostęp za pomocą emulatora Androida. Więcej informacji
- W klasie
FhirApplication
dodaj ten wiersz, aby leniwie utworzyć instancję silnika FHIR:
Dzięki temu instancja FhirEngine jest tworzona tylko przy pierwszym użyciu, a nie natychmiast po uruchomieniu aplikacji.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) }
- Aby ułatwić dostęp do aplikacji w całej aplikacji, dodaj do klasy
FhirApplication
tę wygodną metodę:
Ta metoda statyczna umożliwia pobieranie instancji silnika FHIR z dowolnego miejsca w aplikacji przy użyciu kontekstu.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Synchronizowanie danych z serwerem FHIR
- Utwórz nowe zajęcia
DownloadWorkManagerImpl.kt
. W tej klasie określisz, jak aplikacja będzie pobierać następny zasób z listy do pobrania:
Te zajęcia mają kolejkę typów zasobów, które chcą pobrać. Przetwarza odpowiedzi i wyodrębnia zasoby ze zwróconego pakietu, które są zapisywane w lokalnej bazie danych.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 } }
- Utwórz nową klasę
AppFhirSyncWorker.kt
Ta klasa określa sposób synchronizacji aplikacji ze zdalnym serwerem FHIR przy użyciu instancji roboczej w tle.
Zdefiniowaliśmy tu menedżera pobierania, narzędzie do rozwiązywania konfliktów i instancję silnika FHIR do synchronizacji.class AppFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) : FhirSyncWorker(appContext, workerParams) { override fun getDownloadWorkManager() = DownloadWorkManagerImpl() override fun getConflictResolver() = AcceptLocalConflictResolver override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) }
- W modelu widoku danych
PatientListViewModel.kt
skonfigurujesz mechanizm jednorazowej synchronizacji. Znajdź i dodaj ten kod do funkcjitriggerOneTimeSync()
:
Ta współprogram inicjuje jednorazową synchronizację z serwerem FHIR przy użyciu zdefiniowanego wcześniej obiektu AppFhirSyncWorker. Następnie zaktualizuje interfejs na podstawie stanu procesu synchronizacji.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } }
- W pliku
PatientListFragment.kt
zaktualizuj treść funkcjihandleSyncJobStatus
:
W tym miejscu po zakończeniu procesu synchronizacji zostanie wyświetlony toast z powiadomieniem dla użytkownika, a aplikacja wyświetli wszystkich pacjentów, wywołując wyszukiwanie z pustą nazwą.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Wszystko gotowe, uruchom aplikację. Kliknij przycisk Sync
w menu. Jeśli wszystko działa prawidłowo, pacjentki z lokalnego serwera FHIR powinny być pobierane i wyświetlane w aplikacji.
6. Modyfikowanie i przesyłanie danych pacjentów
W tej sekcji przeprowadzimy Cię przez proces modyfikowania danych pacjentów na podstawie określonych kryteriów i przesyłania zaktualizowanych danych na serwer FHIR. W szczególności zmienimy miasta adresowe w przypadku pacjentów mieszkających w tych miastach: Wakefield
i Taunton
.
Krok 1. Skonfiguruj logikę modyfikacji w PatientListViewModel
Kod z tej sekcji został dodany do funkcji triggerUpdate
w PatientListViewModel
- Dostęp do silnika FHIR: zacznij od uzyskania odniesienia do silnika FHIR w
PatientListViewModel.kt
.
Ten kod uruchamia współrzędną w zakresie ViewModel i inicjuje silnik FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication())
- Wyszukiwanie pacjentów z Wakefield: użyj silnika FHIR do wyszukania pacjentów z miastem adresowym
Wakefield
.
W tym przypadku używamy metodyval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }
search
mechanizmu FHIR do filtrowania pacjentów na podstawie ich miasta adresowego. Wynikiem będzie lista pacjentów z Wakefield. - Wyszukiwanie pacjentów z Taunton: analogicznie, wyszukaj pacjentów z miastem adresowym
Taunton
.
Mamy teraz dwie listy pacjentów – jedną z Wakefielda i drugą z Tunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) }
- Modyfikuj adresy pacjentów:przejrzyj każdego pacjenta na liście
patientsFromWakefield
, zmień jego miasto naTaunton
i zaktualizuj go w silniku FHIR.
W podobny sposób zaktualizuj nazwę każdego pacjenta na liściepatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }
patientsFromTaunton
, tak aby jego miejscowość została zmieniona naWakefield
.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) }
- Zainicjuj synchronizację: po lokalnej modyfikacji danych uruchom jednorazową synchronizację, aby mieć pewność, że dane zostaną zaktualizowane na serwerze FHIR.
Nawias zamykającytriggerOneTimeSync() }
}
oznacza koniec współprogramu uruchomionego na początku.
Krok 2. Przetestuj funkcje
- Testowanie interfejsu:uruchom aplikację. Kliknij przycisk
Update
w menu. Powinny wyświetlić się zamienione miasta adresowe pacjentaAaron697
iAbby752
. - Weryfikacja serwera:otwórz przeglądarkę i wejdź na stronę
http://localhost:8080/fhir/Patient/
. Sprawdź, czy miasto adresowe pacjentówAaron697
iAbby752
jest zaktualizowane na lokalnym serwerze FHIR.
Dzięki wykonaniu tych czynności udało Ci się wdrożyć mechanizm modyfikacji danych pacjentów i synchronizowania zmian z serwerem FHIR.
7. Wyszukaj pacjentów według imienia i nazwiska
Wyszukiwanie pacjentów według ich imion i nazwisk może stanowić łatwy w obsłudze sposób pobierania informacji. Przeprowadzimy Cię przez proces wdrażania tej funkcji w aplikacji.
Krok 1. Zaktualizuj podpis funkcji
Przejdź do pliku PatientListViewModel.kt
i znajdź funkcję o nazwie searchPatientsByName
. Dodamy do tej funkcji kod.
Aby filtrować wyniki na podstawie podanego zapytania o nazwę i przesyłać wyniki do aktualizacji interfejsu użytkownika, uwzględnij ten warunkowy blok kodu:
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 }
}
}
W tym przypadku, jeśli pole nameQuery
nie jest puste, funkcja wyszukiwania przefiltruje wyniki, aby uwzględnić tylko pacjentów, których imiona i nazwiska zawierają określone zapytanie.
Krok 2. Przetestuj nową funkcję wyszukiwania
- Uruchom ponownie aplikację:po wprowadzeniu tych zmian przebuduj i uruchom aplikację.
- Wyszukiwanie pacjentów: na ekranie z listą pacjentów użyj funkcji wyszukiwania. Możesz teraz wpisać imię i nazwisko (lub ich część), aby odpowiednio przefiltrować listę pacjentów.
Po wykonaniu tych czynności aplikacja została wzbogacona o możliwość efektywnego wyszukiwania pacjentów według ich imion i nazwisk. Może to znacznie zwiększyć wygodę użytkowników i efektywność pobierania danych.
8. Gratulacje!
Biblioteka silnika FHIR została przez Ciebie użyta do zarządzania zasobami FHIR w aplikacji:
- Używanie interfejsu Sync API do synchronizowania zasobów FHIR z serwerem FHIR
- Używanie interfejsu Data Access API do tworzenia, odczytywania, aktualizowania i usuwania lokalnych zasobów FHIR
- Użyj interfejsu Search API do wyszukiwania lokalnych zasobów FHIR
Omówione zagadnienia
- Jak skonfigurować lokalny serwer FHIR HAPI
- Jak przesłać dane testowe na lokalny serwer FHIR HAPI
- Jak utworzyć aplikację na Androida przy użyciu biblioteki FHIR Engine
- Jak używać interfejsów API synchronizacji, interfejsu Data Access API i Search API w bibliotece wyszukiwarki FHIR
Następne kroki
- Zapoznaj się z dokumentacją biblioteki FHIR
- Poznaj zaawansowane funkcje interfejsu Search API
- Zastosuj bibliotekę FHIR Engine we własnej aplikacji na Androida