1. ก่อนเริ่มต้น
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะได้สร้างแอป Android โดยใช้ไลบรารี FHIR Engine แอปจะใช้ไลบรารี FHIR Engine เพื่อดาวน์โหลดทรัพยากร FHIR จากเซิร์ฟเวอร์ FHIR และอัปโหลดการเปลี่ยนแปลงในเครื่องไปยังเซิร์ฟเวอร์
สิ่งที่คุณจะได้เรียนรู้
- วิธีสร้างเซิร์ฟเวอร์ HAPI FHIR ในเครื่องโดยใช้ Docker
- วิธีผสานรวมไลบรารี FHIR Engine ในแอปพลิเคชัน Android
- วิธีใช้ Sync API เพื่อตั้งค่างานแบบครั้งเดียวหรือแบบเป็นระยะๆ เพื่อดาวน์โหลดและอัปโหลดทรัพยากร FHIR
- วิธีใช้ Search API
- วิธีใช้ Data Access API เพื่อสร้าง อ่าน อัปเดต และลบทรัพยากร FHIR ในเครื่อง
สิ่งที่ต้องมี
- Docker (รับ Docker)
- Android Studio เวอร์ชันล่าสุด (v4.1.2+)
- โปรแกรมจำลอง Android หรืออุปกรณ์ Android จริงที่ใช้ Android 7.0 Nougat ขึ้นไป
- โค้ดตัวอย่าง
- ความรู้พื้นฐานเกี่ยวกับการพัฒนา Android ใน Kotlin
หากยังไม่เคยสร้างแอป Android มาก่อน ให้เริ่มด้วยการสร้างแอปแรก
2. ตั้งค่าเซิร์ฟเวอร์ HAPI FHIR ภายในด้วยข้อมูลทดสอบ
HAPI FHIR เป็นเซิร์ฟเวอร์ FHIR แบบโอเพนซอร์สที่ได้รับความนิยม เราใช้เซิร์ฟเวอร์ HAPI FHIR ในเครื่องใน Codelab สำหรับแอป 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_sample_data_fhir_r4_sep2019.zip
ข้อมูลที่แยกออกมาแล้วมีไฟล์.json
จำนวนมาก โดยแต่ละไฟล์จะเป็นชุดธุรกรรมสำหรับผู้ป่วยแต่ละราย - เราจะอัปโหลดข้อมูลการทดสอบสำหรับผู้ป่วย 3 รายไปยังเซิร์ฟเวอร์ 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/
- หากต้องการอัปโหลดข้อมูลทดสอบสำหรับผู้ป่วยทุกรายไปยังเซิร์ฟเวอร์ ให้เรียกใช้
อย่างไรก็ตาม การดำเนินการนี้อาจใช้เวลานานและไม่จำเป็นสำหรับ Codelabfor 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
ดาวน์โหลดโค้ด
หากต้องการดาวน์โหลดโค้ดสำหรับ Codelab นี้ ให้โคลนที่เก็บ Android FHIR SDK: git clone https://github.com/google/android-fhir.git
โปรเจ็กต์เริ่มต้นสำหรับ Codelab นี้อยู่ใน codelabs/engine
นําเข้าแอปไปยัง Android Studio
โดยเริ่มจากการนำเข้าแอปเริ่มต้นไปยัง Android Studio
เปิด Android Studio เลือกนำเข้าโปรเจ็กต์ (Gradle, Eclipse ADT ฯลฯ) แล้วเลือกโฟลเดอร์ codelabs/engine/
จากซอร์สโค้ดที่คุณดาวน์โหลดไว้ก่อนหน้านี้
ซิงค์โปรเจ็กต์กับไฟล์ Gradle
เพื่อความสะดวกของคุณ มีการเพิ่มทรัพยากร Dependency ของไลบรารี FHIR Engine ไปยังโปรเจ็กต์แล้ว ซึ่งจะช่วยให้คุณผสานรวมไลบรารี FHIR Engine ในแอปของคุณได้ ดูบรรทัดต่อไปนี้ที่ส่วนท้ายของไฟล์ app/build.gradle.kts
ของโปรเจ็กต์
dependencies {
// ...
implementation("com.google.android.fhir:engine:0.1.0-beta05")
}
คุณควรซิงค์โปรเจ็กต์กับไฟล์ Gradle ในขั้นตอนนี้ เพื่อให้มั่นใจว่าทรัพยากร Dependency ทั้งหมดพร้อมใช้งานสำหรับแอป
เลือกซิงค์โปรเจ็กต์กับไฟล์ Gradle () จากแถบเครื่องมือของ Android Studio นอกจากนี้ คุณยังเรียกใช้แอปอีกครั้งเพื่อตรวจสอบว่าทรัพยากร Dependency ทำงานได้อย่างถูกต้อง
เรียกใช้แอปเริ่มต้น
เมื่อนำเข้าโปรเจ็กต์ไปยัง Android Studio แล้ว คุณก็พร้อมที่จะเรียกใช้แอปเป็นครั้งแรก
เริ่มโปรแกรมจำลอง Android Studio แล้วคลิกเรียกใช้ () ในแถบเครื่องมือ Android Studio
4. สร้างอินสแตนซ์ FHIR Engine
หากต้องการรวม FHIR Engine เข้ากับแอป Android คุณจะต้องใช้ไลบรารี FHIR Engine และเริ่มต้นอินสแตนซ์ของ FHIR Engine ขั้นตอนที่ระบุไว้ด้านล่างจะช่วยแนะนำคุณตลอดกระบวนการ
- ไปที่ชั้นเรียนแอปพลิเคชัน ซึ่งในตัวอย่างนี้คือ
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 แบบ Lazily
การทำเช่นนี้จะช่วยให้มั่นใจว่าอินสแตนซ์ 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 ระยะไกลโดยใช้ผู้ปฏิบัติงานในเบื้องหลัง
ในส่วนนี้ เราได้กำหนดไว้ว่า Download Manager, ตัวแก้ไขข้อขัดแย้ง และอินสแตนซ์ของเครื่องมือ FHIR ใดที่จะใช้สำหรับการซิงค์class AppFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) : FhirSyncWorker(appContext, workerParams) { override fun getDownloadWorkManager() = DownloadWorkManagerImpl() override fun getConflictResolver() = AcceptLocalConflictResolver override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) }
- ใน ViewModel
PatientListViewModel.kt
คุณจะต้องตั้งค่ากลไกการซิงค์แบบครั้งเดียว ค้นหาและเพิ่มโค้ดนี้ลงในฟังก์ชันtriggerOneTimeSync()
:
โครูทีนนี้จะเริ่มการซิงค์แบบครั้งเดียวกับเซิร์ฟเวอร์ FHIR โดยใช้ AppFhirSyncWorker ที่เรากำหนดไว้ก่อนหน้านี้ จากนั้นจะอัปเดต UI ตามสถานะของกระบวนการซิงค์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 และเริ่มต้นเครื่องมือ FHIRviewModelScope.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
ตอนนี้เรามีรายชื่อผู้ป่วย 2 ราย คือ ชื่อคนไข้จากเวกฟิลด์ ส่วนอีกคนมาจากทอนตัน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: ทดสอบฟังก์ชันการทำงาน
- การทดสอบ UI:เรียกใช้แอป คลิกปุ่ม
Update
ในเมนู คุณควรเห็นเมืองที่อยู่ของผู้ป่วยAaron697
และAbby752
สลับกันแล้ว - การยืนยันเซิร์ฟเวอร์:เปิดเบราว์เซอร์และไปที่
http://localhost:8080/fhir/Patient/
ยืนยันว่าเมืองที่อยู่ของผู้ป่วยAaron697
และAbby752
ได้รับการอัปเดตในเซิร์ฟเวอร์ FHIR แล้ว
การทำตามขั้นตอนเหล่านี้หมายความว่าคุณได้นำกลไกการแก้ไขข้อมูลของผู้ป่วยไปใช้และซิงค์ข้อมูลการเปลี่ยนแปลงกับเซิร์ฟเวอร์ FHIR เรียบร้อยแล้ว
7. ค้นหาผู้ป่วยตามชื่อ
การค้นหาผู้ป่วยจากชื่อผู้ป่วยอาจช่วยให้เรียกข้อมูลได้ง่าย ในที่นี้ เราจะแนะนำคุณตลอดขั้นตอนการนำฟีเจอร์นี้ไปใช้ในแอปพลิเคชันของคุณ
ขั้นตอนที่ 1: อัปเดตลายเซ็นฟังก์ชัน
ไปที่ไฟล์ PatientListViewModel.kt
และค้นหาฟังก์ชันชื่อ searchPatientsByName
เราจะเพิ่มโค้ดลงในฟังก์ชันนี้
หากต้องการกรองผลลัพธ์ตามการค้นหาชื่อที่ระบุ และแสดงผลลัพธ์ให้ UI อัปเดต ให้รวมโค้ดบล็อกแบบมีเงื่อนไขต่อไปนี้
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 เพื่อจัดการทรัพยากร FHIR ในแอปของคุณ ดังนี้
- ใช้ Sync API เพื่อซิงค์ทรัพยากร FHIR กับเซิร์ฟเวอร์ FHIR
- ใช้ Data Access API เพื่อสร้าง อ่าน อัปเดต และลบทรัพยากร FHIR ในเครื่อง
- ใช้ Search API เพื่อค้นหาทรัพยากร FHIR ในเครื่อง
สรุปประเด็นที่ได้พูดถึง
- วิธีตั้งค่าเซิร์ฟเวอร์ HAPI FHIR ภายใน
- วิธีอัปโหลดข้อมูลทดสอบไปยังเซิร์ฟเวอร์ HAPI FHIR ในเครื่อง
- วิธีสร้างแอป Android โดยใช้ไลบรารี FHIR Engine
- วิธีใช้ Sync API, Data Access API และ Search API ในไลบรารี FHIR Engine
ขั้นตอนถัดไป
- ดูเอกสารประกอบสำหรับไลบรารี FHIR Engine
- สำรวจฟีเจอร์ขั้นสูงของ Search API
- ใช้ไลบรารี FHIR Engine ในแอป Android ของคุณเอง