1. לפני שמתחילים
מה תפַתחו
ב-codelab הזה, תיצרו אפליקציית Android באמצעות FHIR Engine Library. האפליקציה תשתמש בספריית FHIR Engine כדי להוריד משאבי FHIR משרת FHIR, ולהעלות לשרת שינויים מקומיים.
מה תלמדו
- איך יוצרים שרת HAPI FHIR מקומי באמצעות Docker
- איך משלבים את ספריית FHIR Engine באפליקציה ל-Android
- איך משתמשים ב-Sync API כדי להגדיר משימה חד-פעמית או תקופתית להורדה ולהעלאה של משאבי FHIR
- איך משתמשים ב-Search API
- איך משתמשים בממשקי API לגישה לנתונים כדי ליצור, לקרוא, לעדכן ולמחוק משאבי FHIR באופן מקומי
הדרישות
- Docker (get Docker)
- גרסה עדכנית של Android Studio (מגרסה 4.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-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/ - כדי להעלות לשרת נתוני בדיקה של כל המטופלים, מריצים את הפקודה
עם זאת, השלמת התהליך הזה עשויה להימשך זמן רב, והוא לא נחוץ ל-codelab.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 Bundle, עם ספירה של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, בוחרים באפשרות Import Project (Gradle, Eclipse ADT, etc.) (ייבוא פרויקט (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.
בסרגל הכלים של Android Studio, לוחצים על Sync Project with Gradle Files (סנכרון הפרויקט עם קובצי Gradle) (
). אפשר גם להריץ את האפליקציה שוב כדי לבדוק שהתלות פועלת בצורה תקינה.
הפעלת האפליקציה לתחילת הדרך
אחרי שיובא הפרויקט ל-Android Studio, אפשר להריץ את האפליקציה בפעם הראשונה.
מפעילים את האמולטור של Android Studio ולוחצים על Run (הפעלה) (
) בסרגל הכלים של 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: קובע את אסטרטגיית השגיאות של מסד הנתונים. במקרה כזה, אם מתרחשת שגיאה בפתיחה, מסד הנתונים נוצר מחדש. -
baseUrlinServerConfiguration: כתובת ה-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()ומוסיפים לה את הקוד הזה: שגרת המשך (coroutine) זו מתחילה סנכרון חד-פעמי עם שרת 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 Engine:מתחילים בקבלת הפניה ל-FHIR Engine ב-
PatientListViewModel.kt. הקוד הזה מפעיל שגרת המשך (coroutine) בהיקף של ViewModel ומאתחל את מנוע FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - חיפוש מטופלים מ-Wakefield:משתמשים במנוע FHIR כדי לחפש מטופלים שכתובת העיר שלהם היא
Wakefield. בדוגמה הזו, אנחנו משתמשים בשיטהval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchשל מנוע FHIR כדי לסנן מטופלים על סמך העיר שמופיעה בכתובת שלהם. התוצאה תהיה רשימה של מטופלים מ-Wakefield. - חיפוש מטופלים מהעיר טאונטון:באופן דומה, מחפשים מטופלים שהעיר בכתובת שלהם היא
Taunton. עכשיו יש לנו שתי רשימות של מטופלים – אחת מ-Wakefield והשנייה מ-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 כדי לנהל משאבי 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 Library
- התכונות המתקדמות של Search API
- שימוש בספריית FHIR Engine באפליקציית Android משלכם