1. Прежде чем начать
Что вы построите
В этом практическом занятии вы создадите Android-приложение, используя библиотеку FHIR Engine Library. Ваше приложение будет использовать FHIR Engine Library для загрузки ресурсов FHIR с FHIR-сервера и отправки любых локальных изменений на сервер.
Что вы узнаете
- Как создать локальный сервер HAPI FHIR с помощью Docker
- Как интегрировать библиотеку FHIR Engine в ваше Android-приложение
- Как использовать API синхронизации для настройки разовой или периодической задачи по загрузке и выгрузке ресурсов FHIR.
- Как использовать API поиска
- Как использовать API доступа к данным для создания, чтения, обновления и удаления ресурсов FHIR локально.
Что вам понадобится
- Docker ( получить Docker )
- Последняя версия Android Studio (v4.1.2+)
- Эмулятор Android или физическое устройство Android под управлением Android 7.0 Nougat или более поздней версии.
- Пример кода
- Базовые знания разработки под Android на Kotlin.
Если вы раньше не создавали приложения для Android, вы можете начать с разработки своего первого приложения .
2. Настройте локальный сервер HAPI FHIR с тестовыми данными.
HAPI FHIR — популярный FHIR-сервер с открытым исходным кодом. В нашей практической работе мы используем локальный FHIR-сервер HAPI для подключения Android-приложения.
Настройте локальный сервер HAPI FHIR.
- Выполните следующую команду в терминале, чтобы получить последнюю версию образа HAPI FHIR.
docker pull hapiproject/hapi:latest - Создайте контейнер HAPI FHIR, используя Docker Desktop для запуска ранее загруженного образа
hapiproject/hapiили выполнив следующую команду. Узнать больше .docker run -p 8080:8080 hapiproject/hapi:latest - Проверьте сервер, открыв в браузере URL-адрес
http://localhost:8080/. Вы должны увидеть веб-интерфейс HAPI FHIR.
Заполните локальный сервер HAPI FHIR тестовыми данными.
Для тестирования нашего приложения нам понадобятся тестовые данные на сервере. Мы будем использовать синтетические данные, сгенерированные программой Synthea.
- Сначала нам нужно загрузить примеры данных из synthea-samples . Скачайте и распакуйте
synthea_sample_data_fhir_r4_sep2019.zip. Распакованные примеры данных содержат множество файлов.json, каждый из которых представляет собой пакет транзакций для отдельного пациента. - Мы загрузим тестовые данные для трех пациентов на локальный сервер HAPI FHIR. Выполните следующую команду в каталоге, содержащем файлы 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/ - Для загрузки тестовых данных всех пациентов на сервер выполните следующую команду:
Однако выполнение этого задания может занять много времени и не является обязательным для практического занятия.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - Убедитесь, что тестовые данные доступны на сервере, открыв в браузере URL-адрес
http://localhost:8080/fhir/Patient/. В результатах поиска вы должны увидеть текстHTTP 200 OKи раздел «Response Bodyстраницы, содержащей данные о пациентах в пакете FHIR, с указаниемtotalколичества результатов.
3. Настройте приложение для Android.
Скачать код
Чтобы загрузить код для этого практического занятия, клонируйте репозиторий Android FHIR SDK: git clone https://github.com/google/android-fhir.git
Стартовый проект для этой практической работы находится в codelabs/engine .
Импортируйте приложение в Android Studio.
Начнём с импорта стартового приложения в Android Studio.
Откройте Android Studio, выберите «Импорт проекта» (Gradle, Eclipse ADT и т. д.) и выберите папку codelabs/engine/ из исходного кода, который вы скачали ранее.

Синхронизируйте свой проект с файлами Gradle.
Для вашего удобства зависимости библиотеки FHIR Engine уже добавлены в проект. Это позволит вам интегрировать библиотеку FHIR Engine в ваше приложение. Обратите внимание на следующие строки в конце файла app/build.gradle.kts вашего проекта:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Чтобы убедиться, что все зависимости доступны вашему приложению, на этом этапе следует синхронизировать проект с файлами Gradle.
Выберите «Синхронизировать проект с файлами Gradle» (
) из панели инструментов Android Studio. Вы также можете запустить приложение еще раз, чтобы проверить корректность работы зависимостей.
Запустите стартовое приложение
Теперь, когда вы импортировали проект в Android Studio, вы готовы запустить приложение в первый раз.
Запустите эмулятор Android Studio и нажмите «Запустить» (
) на панели инструментов Android Studio.

4. Создайте экземпляр FHIR Engine.
Для интеграции FHIR Engine в ваше Android-приложение вам потребуется использовать библиотеку FHIR Engine и запустить экземпляр FHIR Engine. Ниже описаны шаги, которые помогут вам в этом процессе.
- Перейдите к классу Application, который в данном примере называется
FhirApplication.ktи находится в папкеapp/src/main/java/com/google/android/fhir/codelabs/engine. - Внутри метода
onCreate()добавьте следующий код для инициализации FHIR Engine: Примечания: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: Включает шифрование данных, если устройство его поддерживает. -
RECREATE_AT_OPEN: Определяет стратегию обработки ошибок базы данных. В данном случае база данных пересоздается, если при открытии возникает ошибка. -
baseUrlвServerConfiguration: это базовый URL-адрес FHIR-сервера. Предоставленный IP-адрес10.0.2.2специально зарезервирован для localhost и доступен из эмулятора Android. Подробнее .
-
- В класс
FhirApplicationдобавьте следующую строку для отложенного создания экземпляра FHIR Engine: Это гарантирует, что экземпляр FhirEngine будет создан только при первом обращении к нему, а не сразу после запуска приложения.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Добавьте следующий вспомогательный метод в класс
FhirApplicationдля более удобного доступа ко всему приложению: Этот статический метод позволяет получить доступ к экземпляру FHIR Engine из любой точки приложения, используя контекст.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Синхронизация данных с сервером FHIR.
- Создайте новый класс
DownloadWorkManagerImpl.kt. В этом классе вы определите, как приложение будет выбирать следующий ресурс из списка для загрузки. Этот класс имеет очередь типов ресурсов, которые он хочет загрузить. Он обрабатывает ответы и извлекает ресурсы из возвращенного пакета, которые сохраняются в локальной базе данных.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 } } - Создайте новый класс
AppFhirSyncWorker.ktЭтот класс определяет, как приложение будет синхронизироваться с удаленным FHIR-сервером с помощью фонового рабочего процесса. Здесь мы определили, какой менеджер загрузок, средство разрешения конфликтов и экземпляр движка FHIR использовать для синхронизации.class AppFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) : FhirSyncWorker(appContext, workerParams) { override fun getDownloadWorkManager() = DownloadWorkManagerImpl() override fun getConflictResolver() = AcceptLocalConflictResolver override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) override fun getUploadStrategy() = UploadStrategy.forBundleRequest( methodForCreate = HttpCreateMethod.PUT, methodForUpdate = HttpUpdateMethod.PATCH, squash = true, bundleSize = 500, ) } - В вашем ViewModel,
PatientListViewModel.kt, необходимо настроить механизм однократной синхронизации. Найдите и добавьте следующий код в функциюtriggerOneTimeSync(): Эта сопрограмма инициирует однократную синхронизацию с FHIR-сервером, используя определенный нами ранее объект AppFhirSyncWorker. Затем она обновит пользовательский интерфейс в зависимости от состояния процесса синхронизации.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - В файле
PatientListFragment.ktобновите тело функцииhandleSyncJobStatus: После завершения процесса синхронизации на экране появится всплывающее сообщение, уведомляющее пользователя, и приложение отобразит всех пациентов, выполнив поиск по пустому имени.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Теперь, когда все настроено, запустите приложение. Нажмите кнопку Sync в меню. Если все работает правильно, вы должны увидеть, как данные о пациентах с вашего локального FHIR-сервера загружаются и отображаются в приложении.

6. Изменение и загрузка данных пациента.
В этом разделе мы расскажем вам, как изменить данные пациентов на основе определенных критериев и загрузить обновленные данные на ваш FHIR-сервер. В частности, мы заменим города-адреса для пациентов, проживающих в Wakefield и Taunton .
Шаг 1 : Настройте логику модификации в PatientListViewModel.
Код в этом разделе добавляется в функцию triggerUpdate в PatientListViewModel
- Для доступа к движку FHIR начните с получения ссылки на движок FHIR в файле
PatientListViewModel.kt. Этот код запускает сопрограмму в области видимости ViewModel и инициализирует движок FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Поиск пациентов из Уэйкфилда : Используйте поисковую систему FHIR для поиска пациентов, адрес которых указан как
Wakefield. Здесь мы используем методval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchсистемы FHIR для фильтрации пациентов по городу их проживания. В результате будет получен список пациентов из Уэйкфилда. - Поиск пациентов из Тонтона : Аналогично, выполните поиск пациентов, у которых в качестве адреса указан город
Taunton. Теперь у нас есть два списка пациентов — один из Уэйкфилда, а другой из Тонтона.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - Изменение адресов пациентов : Пройдитесь по каждому пациенту в списке
patientsFromWakefield, измените его город наTauntonи обновите данные в системе FHIR. Аналогичным образом обновите данные каждого пациента в спискеpatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTaunton, изменив его город наWakefield.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - Инициировать синхронизацию : После внесения изменений в данные локально, запустите одноразовую синхронизацию, чтобы убедиться, что данные обновлены на сервере FHIR.
Закрывающая фигурная скобкаtriggerOneTimeSync() }}обозначает конец сопрограммы, запущенной в начале.
Шаг 2 : Проверка функциональности
- Тестирование пользовательского интерфейса : Запустите приложение. Нажмите кнопку
Updateв меню. Вы должны увидеть, что адреса городов пациентовAaron697иAbby752поменяны местами. - Проверка сервера : Откройте браузер и перейдите по адресу
http://localhost:8080/fhir/Patient/. Убедитесь, что город проживания пациентовAaron697иAbby752обновлен на локальном FHIR-сервере.
Выполнив эти шаги, вы успешно внедрили механизм для изменения данных пациентов и синхронизации изменений с вашим FHIR-сервером.
7. Поиск пациентов по имени.
Поиск пациентов по имени может обеспечить удобный способ получения информации. В этой статье мы расскажем, как реализовать эту функцию в вашем приложении.
Шаг 1 : Обновите сигнатуру функции.
Перейдите в файл PatientListViewModel.kt и найдите функцию с именем searchPatientsByName . Мы добавим код в эту функцию.
Для фильтрации результатов на основе предоставленного запроса по имени и вывода результатов в пользовательский интерфейс для обновления, используйте следующий блок условного кода:
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 }
}
}
В этом случае, если поле nameQuery не пустое, функция поиска отфильтрует результаты, включив только пациентов, чьи имена содержат указанный запрос.
Шаг 2 : Проверьте новую функцию поиска.
- Перезапустите приложение : После внесения этих изменений пересоберите и запустите приложение.
- Поиск пациентов : На экране списка пациентов воспользуйтесь функцией поиска. Теперь вы сможете ввести имя (или часть имени), чтобы отфильтровать список пациентов соответствующим образом.
Выполнив эти шаги, вы улучшили свое приложение, предоставив пользователям возможность эффективно искать пациентов по их именам. Это может значительно улучшить пользовательский опыт и повысить эффективность поиска данных.
8. Поздравляем!
Вы использовали библиотеку FHIR Engine Library для управления ресурсами FHIR в своем приложении:
- Используйте API синхронизации для синхронизации ресурсов FHIR с сервером FHIR.
- Используйте API доступа к данным для создания, чтения, обновления и удаления локальных ресурсов FHIR.
- Используйте Search API для поиска локальных ресурсов FHIR.
Что мы рассмотрели
- Как настроить локальный сервер HAPI FHIR
- Как загрузить тестовые данные на локальный сервер HAPI FHIR
- Как создать Android-приложение с использованием библиотеки FHIR Engine.
- Как использовать API синхронизации, API доступа к данным и API поиска в библиотеке FHIR Engine.
Следующие шаги
- Изучите документацию по библиотеке FHIR Engine.
- Изучите расширенные возможности API поиска.
- Примените библиотеку FHIR Engine в своем собственном приложении для Android.