Mengelola resource FHIR menggunakan FHIR Engine Library

1. Sebelum memulai

Yang akan Anda build

Dalam codelab ini, Anda akan membuat aplikasi Android menggunakan FHIR Engine Library. Aplikasi Anda akan menggunakan FHIR Engine Library untuk mendownload resource FHIR dari server FHIR, dan mengupload perubahan lokal ke server.

Yang akan Anda pelajari

  • Cara membuat server HAPI FHIR lokal menggunakan Docker
  • Cara mengintegrasikan FHIR Engine Library ke dalam aplikasi Android Anda
  • Cara menggunakan Sync API untuk menyiapkan tugas satu kali atau berkala guna mendownload dan mengupload resource FHIR
  • Cara menggunakan Search API
  • Cara menggunakan Data Access API untuk membuat, membaca, memperbarui, dan menghapus resource FHIR secara lokal

Yang Anda butuhkan

Jika belum pernah membuat aplikasi Android, Anda dapat memulai dengan membuat aplikasi pertama Anda.

2. Menyiapkan server HAPI FHIR lokal dengan data pengujian

HAPI FHIR adalah server FHIR open source yang populer. Kita menggunakan server HAPI FHIR lokal dalam codelab agar aplikasi Android dapat terhubung.

Menyiapkan server HAPI FHIR lokal

  1. Jalankan perintah berikut di terminal untuk mendapatkan image HAPI FHIR terbaru
    docker pull hapiproject/hapi:latest
    
  2. Buat container HAPI FHIR dengan menggunakan Docker Desktop untuk menjalankan image hapiproject/hapi yang sebelumnya didownload, atau menjalankan perintah berikut
    docker run -p 8080:8080 hapiproject/hapi:latest
    
    Pelajari lebih lanjut.
  3. Periksa server dengan membuka URL http://localhost:8080/ di browser. Anda akan melihat antarmuka web HAPI FHIR.Antarmuka web HAPI FHIR

Mengisi server HAPI FHIR lokal dengan data pengujian

Untuk menguji aplikasi, kita memerlukan beberapa data pengujian di server. Kita akan menggunakan data sintetis yang dibuat oleh Synthea.

  1. Pertama, kita perlu mendownload data contoh dari synthea-samples. Download dan ekstrak synthea_sample_data_fhir_r4_sep2019.zip. Data contoh yang belum di-unzip memiliki banyak file .json, yang masing-masing merupakan paket transaksi untuk setiap pasien.
  2. Kita akan mengupload data pengujian untuk tiga pasien ke server HAPI FHIR lokal. Jalankan perintah berikut di direktori yang berisi 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/
    
  3. Untuk mengupload data pengujian semua pasien ke server, jalankan
    for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done
    
    Namun, proses ini dapat memerlukan waktu yang lama dan tidak diperlukan untuk codelab ini.
  4. Verifikasi bahwa data pengujian tersedia di server dengan membuka URL http://localhost:8080/fhir/Patient/ di browser. Anda akan melihat teks HTTP 200 OK dan bagian Response Body halaman yang berisi data pasien dalam FHIR Bundle sebagai hasil penelusuran dengan jumlah total.Menguji data di server

3. Menyiapkan aplikasi Android

Mendownload Kode

Untuk mendownload kode codelab ini, buat clone repositori Android FHIR SDK: git clone https://github.com/google/android-fhir.git

Project awal untuk codelab ini terletak di codelabs/engine.

Mengimpor aplikasi ke Android Studio

Kita mulai dengan mengimpor aplikasi awal ke Android Studio.

Buka Android Studio, pilih Import Project (Gradle, Eclipse ADT, etc.), lalu pilih folder codelabs/engine/ dari kode sumber yang telah Anda download sebelumnya.

Layar awal Android Studio

Sinkronkan project Anda dengan file Gradle

Untuk memudahkan Anda, dependensi FHIR Engine Library telah ditambahkan ke project. Hal ini memungkinkan Anda mengintegrasikan FHIR Engine Library di aplikasi Anda. Perhatikan baris berikut hingga akhir file app/build.gradle.kts project Anda:

dependencies {
    // ...

    implementation("com.google.android.fhir:engine:1.1.0")
}

Untuk memastikan bahwa semua dependensi tersedia untuk aplikasi Anda, Anda harus menyinkronkan project dengan file gradle pada tahap ini.

Pilih Sync Project with Gradle Files (Tombol sinkronisasi Gradle) dari toolbar Android Studio. Anda juga dapat menjalankan aplikasi lagi untuk memeriksa apakah dependensi berfungsi dengan benar.

Menjalankan aplikasi awal

Setelah mengimpor project ke Android Studio, Anda siap menjalankan aplikasi untuk pertama kalinya.

Mulai emulator Android Studio, lalu klik Run (Tombol Run) di toolbar Android Studio.

Aplikasi Hello World

4. Buat instance FHIR Engine

Untuk menyertakan FHIR Engine ke dalam aplikasi Android Anda, Anda harus menggunakan FHIR Engine Library dan memulai instance FHIR Engine. Langkah-langkah yang diuraikan di bawah ini akan memandu Anda melalui prosesnya.

  1. Buka class Application Anda, yang dalam contoh ini adalah FhirApplication.kt, yang terletak di app/src/main/java/com/google/android/fhir/codelabs/engine.
  2. Di dalam metode onCreate(), tambahkan kode berikut untuk melakukan inisialisasi 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)
                },
            ),
          ),
      )
    
    Catatan:
    • enableEncryptionIfSupported: Mengaktifkan enkripsi data jika perangkat mendukungnya.
    • RECREATE_AT_OPEN: Menentukan strategi error database. Dalam hal ini, database akan dibuat ulang jika terjadi error saat dibuka.
    • baseUrl di ServerConfiguration: Ini adalah URL dasar server FHIR. Alamat IP 10.0.2.2 yang diberikan secara khusus dicadangkan untuk localhost, yang dapat diakses dari emulator Android. Pelajari lebih lanjut.
  3. Di class FhirApplication, tambahkan baris berikut untuk membuat instance FHIR Engine secara lambat:
      private val fhirEngine: FhirEngine by
          lazy { FhirEngineProvider.getInstance(this) }
    
    Hal ini memastikan instance FhirEngine hanya dibuat saat diakses untuk pertama kalinya, bukan segera saat aplikasi dimulai.
  4. Tambahkan metode praktis berikut di class FhirApplication untuk akses yang lebih mudah di seluruh aplikasi Anda:
    companion object {
        fun fhirEngine(context: Context) =
            (context.applicationContext as FhirApplication).fhirEngine
    }
    
    Metode statis ini memungkinkan Anda mengambil instance FHIR Engine dari mana saja di aplikasi menggunakan konteks.

5. Menyinkronkan data dengan server FHIR

  1. Buat class baru DownloadWorkManagerImpl.kt. Dalam class ini, Anda akan menentukan cara aplikasi mengambil resource berikutnya dari daftar untuk didownload.:
      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
        }
      }
    
    Class ini memiliki antrean jenis resource yang ingin didownload. Proses ini memproses respons dan mengekstrak resource dari paket yang ditampilkan, yang akan disimpan ke dalam database lokal.
  2. Buat class baru AppFhirSyncWorker.kt Class ini menentukan cara aplikasi akan menyinkronkan dengan server FHIR jarak jauh menggunakan pekerja latar belakang.
    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,
        )
    }
    
    Di sini, kita telah menentukan pengelola download, pemecah konflik, dan instance mesin FHIR yang akan digunakan untuk menyinkronkan.
  3. Di ViewModel Anda, PatientListViewModel.kt, Anda akan menyiapkan mekanisme sinkronisasi satu kali. Cari dan tambahkan kode ini ke fungsi triggerOneTimeSync():
    viewModelScope.launch {
          Sync.oneTimeSync<AppFhirSyncWorker>(getApplication())
            .shareIn(this, SharingStarted.Eagerly, 10)
            .collect { _pollState.emit(it) }
        }
    
    Coroutine ini memulai sinkronisasi satu kali dengan server FHIR menggunakan AppFhirSyncWorker yang kita tentukan sebelumnya. Kemudian, UI akan diperbarui berdasarkan status proses sinkronisasi.
  4. Di file PatientListFragment.kt, perbarui isi fungsi handleSyncJobStatus:
    when (syncJobStatus) {
        is SyncJobStatus.Finished -> {
            Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show()
            viewModel.searchPatientsByName("")
        }
        else -> {}
    }
    
    Di sini, saat proses sinkronisasi selesai, pesan toast akan ditampilkan untuk memberi tahu pengguna, dan aplikasi kemudian akan menampilkan semua pasien dengan memanggil penelusuran menggunakan nama kosong.

Setelah semuanya disiapkan, jalankan aplikasi Anda. Klik tombol Sync di menu. Jika semuanya berfungsi dengan benar, Anda akan melihat pasien dari server FHIR lokal Anda didownload dan ditampilkan di aplikasi.

Daftar pasien

6. Mengubah dan Mengupload Data Pasien

Di bagian ini, kami akan memandu Anda melalui proses mengubah data pasien berdasarkan kriteria tertentu dan mengupload data yang telah diubah ke server FHIR Anda. Secara khusus, kami akan menukar kota alamat untuk pasien yang tinggal di Wakefield dan Taunton.

Langkah 1: Menyiapkan Logika Modifikasi di PatientListViewModel

Kode di bagian ini ditambahkan ke fungsi triggerUpdate di PatientListViewModel

  1. Mengakses FHIR Engine:Mulai dengan mendapatkan referensi ke FHIR Engine di PatientListViewModel.kt.
    viewModelScope.launch {
       val fhirEngine = FhirApplication.fhirEngine(getApplication())
    
    Kode ini meluncurkan coroutine dalam cakupan ViewModel dan menginisialisasi mesin FHIR.
  2. Menelusuri Pasien dari Wakefield:Gunakan mesin FHIR untuk menelusuri pasien dengan kota alamat Wakefield.
    val patientsFromWakefield =
         fhirEngine.search<Patient> {
           filter(
             Patient.ADDRESS_CITY,
             {
               modifier =  StringFilterModifier.MATCHES_EXACTLY
               value = "Wakefield"
             }
           )
         }
    
    Di sini, kita menggunakan metode search mesin FHIR untuk memfilter pasien berdasarkan kota alamat mereka. Hasilnya akan berupa daftar pasien dari Wakefield.
  3. Menelusuri Pasien dari Taunton:Demikian pula, telusuri pasien dengan kota alamat Taunton.
    val patientsFromTaunton =
         fhirEngine.search<Patient> {
           filter(
             Patient.ADDRESS_CITY,
             {
               modifier =  StringFilterModifier.MATCHES_EXACTLY
               value = "Taunton"
             }
           )
         }
    
    Sekarang kita memiliki dua daftar pasien - satu dari Wakefield dan yang lainnya dari Taunton.
  4. Mengubah Alamat Pasien:Periksa setiap pasien dalam daftar patientsFromWakefield, ubah kotanya menjadi Taunton, dan perbarui di mesin FHIR.
    patientsFromWakefield.forEach {
         it.resource.address.first().city = "Taunton"
         fhirEngine.update(it.resource)
    }
    
    Demikian pula, perbarui setiap pasien dalam daftar patientsFromTaunton agar kotanya diubah menjadi Wakefield.
    patientsFromTaunton.forEach {
         it.resource.address.first().city = "Wakefield"
         fhirEngine.update(it.resource)
    }
    
  5. Mulai Sinkronisasi:Setelah mengubah data secara lokal, picu sinkronisasi satu kali untuk memastikan data diperbarui di server FHIR.
    triggerOneTimeSync()
    }
    
    Kurung kurawal penutup } menandakan akhir coroutine yang diluncurkan di awal.

Langkah 2: Menguji Fungsi

  1. Pengujian UI:Jalankan aplikasi Anda. Klik tombol Update di menu. Anda akan melihat kota alamat untuk pasien Aaron697 dan Abby752 ditukar.
  2. Verifikasi Server:Buka browser dan buka http://localhost:8080/fhir/Patient/. Pastikan kota alamat untuk pasien Aaron697 dan Abby752 diperbarui di server FHIR lokal.

Dengan mengikuti langkah-langkah ini, Anda telah berhasil menerapkan mekanisme untuk mengubah data pasien dan menyinkronkan perubahan dengan server FHIR Anda.

7. Menelusuri Pasien berdasarkan Nama

Menelusuri pasien berdasarkan nama mereka dapat memberikan cara yang mudah digunakan untuk mengambil informasi. Di sini, kami akan memandu Anda melalui proses penerapan fitur ini di aplikasi Anda.

Langkah 1: Perbarui Tanda Tangan Fungsi

Buka file PatientListViewModel.kt dan temukan fungsi bernama searchPatientsByName. Kita akan menambahkan kode ke dalam fungsi ini.

Untuk memfilter hasil berdasarkan kueri nama yang diberikan, dan memunculkan hasil agar UI diperbarui, gabungkan blok kode bersyarat berikut:

    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 }
      }
    }

Di sini, jika nameQuery tidak kosong, fungsi penelusuran akan memfilter hasil untuk hanya menyertakan pasien yang namanya berisi kueri yang ditentukan.

Langkah 2: Menguji Fungsi Penelusuran Baru

  1. Luncurkan Ulang Aplikasi:Setelah melakukan perubahan ini, bangun ulang dan jalankan aplikasi Anda.
  2. Menelusuri Pasien: Di layar daftar pasien, gunakan fungsi penelusuran. Sekarang Anda dapat memasukkan nama (atau sebagian nama) untuk memfilter daftar pasien.

Setelah menyelesaikan langkah-langkah ini, Anda telah meningkatkan kualitas aplikasi dengan memberi pengguna kemampuan untuk menelusuri pasien secara efisien berdasarkan nama mereka. Hal ini dapat meningkatkan pengalaman pengguna dan efisiensi dalam pengambilan data secara signifikan.

8. Selamat!

Anda telah menggunakan FHIR Engine Library untuk mengelola resource FHIR di aplikasi Anda:

  • Menggunakan Sync API untuk menyinkronkan resource FHIR dengan server FHIR
  • Menggunakan Data Access API untuk membuat, membaca, memperbarui, dan menghapus resource FHIR lokal
  • Menggunakan Search API untuk menelusuri resource FHIR lokal

Yang telah kita bahas

  • Cara menyiapkan server HAPI FHIR lokal
  • Cara mengupload data pengujian ke Server HAPI FHIR lokal
  • Cara membangun aplikasi Android menggunakan FHIR Engine Library
  • Cara menggunakan Sync API, Data Access API, dan Search API di FHIR Engine Library

Langkah Berikutnya

  • Mempelajari dokumentasi untuk FHIR Engine Library
  • Menjelajahi fitur lanjutan Search API
  • Menerapkan FHIR Engine Library di aplikasi Android Anda sendiri

Pelajari Lebih Lanjut