บทความและข่าวสาร | Seven Peaks Insights

Hilt –โซลูชัน DI สำหรับ Android Developer ที่ Jetpack แนะนำให้ใช้

แนะนำวิธีการใช้งานอย่างละเอียดสำหรับการพัฒนาแอปพลิเคชันบน Android ในปี 2022

1920 - A detailed guide for andriod dev 2022

 

วิธีนำ Hilt library มาใช้ในการพัฒนาบน Android

ใน session สำหรับแบ่งปันความรู้ของทีมงานที่ Seven Peaks Software บรรดาผู้เชี่ยวชาญด้าน Android ของเราได้พูดถึง Hilt ซึ่งเป็นไลบรารี DI สำหรับ Android พร้อมกับเล่าว่ามันทำงานอย่างไรในกระบวนการพัฒนาแอปพลิเคชันบน Android และสิ่งสำคัญก็คือ มีเคสการใช้งานบางเคสที่พวกเขาได้ลองใช้ซึ่งอาจเป็นประโยชน์สำหรับคุณ เราจึงอยากเล่าให้คุณฟังว่าเป็นอย่างไร

ประโยชน์ของการพัฒนาแอปพลิเคชันบน Android ด้วย Hilt

คุณอาจจะสงสัยว่าทำไมต้องใช้ Hilt ด้วย ต้องขออธิบายก่อนว่า Hilt คือ dependency injection (DI) library สำหรับ Android ที่สร้างขึ้นบน Dagger เพื่อใช้ประสิทธิภาพของ Dagger ทั้งในด้านความแม่นยำของเวลาในการ compile เวลาที่ใช้ในการประมวลผล ความสามารถในการขยายขอบเขตการใช้งาน และการรองรับการใช้งานบน Android Studio ซึ่ง Hilt ช่วยให้การนำ dependency injection หรือการส่งต่อ dependency แทนการสร้างขึ้นมาใหม่ ของ Dagger มาผนวกรวมกับแอปพลิเคชันบน Android เป็นเรื่องง่ายขึ้น

ด้วยเหตุนี้ บริษัทมากมายจึงเริ่มหันมาใช้ Hilt กับแอปพลิเคชันบน Android ของพวกเขามากขึ้นเพราะสามารถรันได้เสถียรและใช้งานง่ายกว่านั่นเอง

และนี่คือตัวอย่างประโยชน์ที่ได้จากการใช้งาน Hilt

การทำงานร่วมกับ Jetpack

  • ส่งต่อ ViewModel object ได้ด้วย Hilt
  • ทำงานร่วมกับ navigation library ของ Jetpack ได้
  • ทำงานร่วมกับ Jetpack Compose ได้
  • ส่งต่อ WorkManager ได้ด้วย Hilt

ติดตั้งง่าย

นักพัฒนาสามารถเพิ่ม dependencies เหล่านี้เข้าไปในไฟล์ gradle ที่อยู่ในระดับ app level ได้ ด้วยคำสั่งต่อไปนี้

// Hilt implementation "com.google.dagger:hilt-android:2.38.1" kapt "com.google.dagger:hilt-compiler:2.38.1" implementation 'androidx.hilt:hilt-navigation-fragment:1.0.0'

// Hilt tests testImplementation 'com.google.dagger:hilt-android-testing:2.38.1' kaptTest 'com.google.dagger:hilt-android-compiler:2.38.1'

// Hilt UI tests androidTestImplementation 'com.google.dagger:hilt-android-testing:2.38.1' kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.38.1'

หลังจากนั้น Hilt ก็จะพร้อมใช้งานและสามารถใช้ annotation เหล่านี้ได้

  • @HiltAndroidApp – สำหรับ class ของแอปพลิเคชัน
  • @AndroidEntryPoint – Activity หรือ Fragment สำหรับการส่งต่อ
  • @HiltViewModel – สำหรับ ViewModel

Hilt เป็น Compile time DIหมายความว่ามันไม่มี instantiation ในระหว่างประมวลผล ซึ่งทำให้

การทดสอบง่ายขึ้น ด้วยการใช้เพียงแค่ 1 annotation ซึ่งก็คือ @HiltAndroidTest

…แต่ยังมีข้อเสียบางอย่าง นั่นคือ

  • ไม่รองรับการทำงานของ FragmentScenario ดังนั้น การทดสอบ UI จึงจำเป็นต้องใช้ boilerplate แต่ Google ก็มีวิธีแก้ไขเรื่องนี้แล้ว

  • Log ไม่ชัดเจนทำให้การ debug ยากขึ้น

กระบวนการทำงานของ Hilt

มาดูกันว่า annotation ต่างๆ ของ Hilt ทำงานร่วมกันเพื่อสร้างโค้ดอย่างไร

Hilt-08.12.2021-2

 

จากบทความแนะนำการพัฒนาแบบ MAD หรือ Modern Android Development ที่เราได้ข้อมูลมาจาก Android developer ผู้เชี่ยวชาญ ทำให้เรารู้ว่า Hilt ใช้ annotation processor สำหรับการสร้างโค้ด ดังนั้น เมื่อแปลงซอร์สไฟล์เป็น Java bytecode แล้ว compiler จะทำการประมวลผล annotation ซึ่ง annotation ที่อยู่ในซอร์สไฟล์จะไป activate การทำงานของ annotation processor อย่างที่ชื่อของมันบอกไว้นั่นเอง

หลังจากนั้น พวกมันจะทำการตรวจสอบ annotation และ type เพื่อควบคุมกิจกรรมต่างๆ อย่างเช่น การสร้างและตรวจสอบซอร์สใหม่ๆ เป็นต้น

คุณสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับกระบวนการทำงานของ Hilt และ Dagger ได้จากคลิปวิดีโอเกี่ยวกับทักษะการทำ MAD

Component ต่างๆ ของ Hilt และวงจรชีวิตของพวกมัน

Hilt แตกต่างจาก Dagger ตรงที่มี component ที่กำหนดมาให้แล้วและ builtin อยู่ในตัวมันเอง พร้อมด้วย scope annotation เพื่อให้นักพัฒนาสามารถส่งต่อไปยัง component ของแอปพลิเคชัน Android ตามลำดับวงจรชีวิตอย่าง Activity, Fragment หรือ viewModel เป็นต้น ได้อย่างอัตโนมัติ

แผนภูมิและตัวอย่างโค้ดด้านล่างนี้จะแสดงให้เห็นลำดับชั้น component ของ Hilt

scope annotation ที่อยู่เหนือแต่ละ component แสดงให้เห็นถึง scope ของ binding ต่างๆ ที่เกี่ยวข้องกับอายุของ component และลูกศรที่อยู่ข้างล่างแต่ละ component จะชี้ไปยัง child component อีกที ซึ่ง binding ในตัว child component นั้น โดยปกติแล้วสามารถขึ้นอยู่กับ binding อันใดก็ได้ของ component ที่อยู่ก่อนหน้า

 
Hilt-08.12.2021-1

 

เมื่อพูดถึงอายุของ component แล้ว มีความเกี่ยวข้องที่สำคัญระหว่างอายุของ component กับอายุของ binding อยู่ โดยในกระบวนการสร้างและทำลาย component นั้นจะไปจำกัดอายุของ binding ที่กำกับอยู่ นอกจากนี้ ยังแสดงเวลาที่เหมาะสมเพื่อใช้งาน value ที่ member ทั้งหลายส่งต่อไปด้วย

ในตารางด้านล่างนี้ คุณจะเห็นว่าแต่ละ scope annotation ของ component และอายุที่กำหนดไว้เป็นอย่างไร

japp95k430w3x1hhap8x


เพิ่มโมดูลของ Hilt ได้ง่ายๆ

โมดูลของ Hilt คือคลาสที่อ้างอิงด้วย annotation @Module ซึ่งผู้ใช้สามารถใช้ annotation เพิ่มเติมอย่าง @InstallIn เพื่อกำหนดว่า component ไหนของ Hilt ที่จะไปอยู่ในกระบวนการติดตั้งของโมดูลนั้นๆ

ขั้นตอนในการเพิ่มโมดูลนั้นไม่ซับซ้อน โดยหลักการแล้ว นักพัฒนาจำเป็นต้องสร้าง annotation สำหรับคลาสของโมดูลด้วย @Module และระบุชื่อ component ที่ต้องการติดตั้งโมดูลลงไป สามารถดูตัวอย่างได้จาก Interfaces ในรูปข้างล่างนี้

หากคุณใช้งาน repositories อยู่ คุณสามารถใช้ annotation อย่าง @Binds ได้ ในส่วนของ Providers นั้นหากคุณมี builder จากไลบรารีอื่นอย่าง Retrofit หรือ Moshi คุณก็สามารถใช้ annotation ที่ชื่อ @Provides ได้

Hilt-08.12.2021


ทดสอบการติดตั้ง

สิ่งที่ต้องทำต่อมาก็คือการทดสอบ ก่อนที่จะใช้งาน HiltTestApplication ได้นั้น นักพัฒนาต้องสร้าง test runner ใหม่ขึ้นมาเสียก่อน เจ้าสิ่งนี้จะทำให้ Hilt สามารถทดสอบด้วย instrumented test ทั้งหมดในโปรเจกต์ได้

ในขั้นแรก สร้างคลาส CustomTestRunner ขึ้นมาเพื่อขยายความสามารถของ AndroidJUnitRunner จากนั้น override ด้วยฟังก์ชัน newApplication และส่งชื่อของ HiltTestApplication ไปยังคลาสที่สร้างขึ้นมา ขั้นตอนต่อไป ตั้งค่า test runner ในไฟล์ Gradle เพื่อให้แน่ใจว่า classpath ทั้งหมดมีการนำไปใช้งาน

Hilt-08.12.2021-3

 

ในระหว่างการทดสอบ จะมีบางกรณีที่นักพัฒนาต้องการแทนที่บางโมดูล ดังนั้น หากระบบออกแบบมาให้นักพัฒนาสามารถแทนที่ binding ใน production ด้วย binding ปลอม หรือ binding ที่เป็นแบบจำลองได้ ก็จะมีประโยชน์มาก เพื่อให้การทดสอบนั้นไม่ได้รับผลกระทบจากปัจจัยภายนอกหรือกำหนดกฎเกณฑ์ได้ง่ายขึ้น

การจะทำแบบนั้นได้ นักพัฒนาต้องสร้างโมดูลสำหรับทดสอบแยกออกมาพร้อมกับ annotate ด้วย @TestInstallIn นอกจากนั้นยังต้องระบุ component ของโมดูลที่ว่า และโมดูลที่จะไปแทนที่ให้ชัดเจนด้วย

Hilt-08.12.2021-5


การถอนการติดตั้งโมดูลของ @InstallIn ใน production สำหรับการทดสอบแต่ละอย่าง นักพัฒนาควรจัดการกับการทดสอบที่ใช้ annotation @UninstallModules หลังจากที่ลบออกแล้วจึงจะสามารถติดตั้ง binding ใหม่เฉพาะสำหรับการทดสอบนั้นๆ ได้

Hilt-08.12.2021-6


อย่างไรก็ดี การแทนที่โมดูลในการทดสอบแต่ละอย่างนั้นยังมีข้อเสียอยู่เหมือนกัน ได้แก่

  • อาจมี error ในการ compile ถ้าหากนักพัฒนาพยายามถอนการติดตั้งโมดูลที่ไม่ได้ annotate ด้วย @InstallIn
  • นอกจากนั้น พวกเขาสามารถลบโมดูล @InstallIn ได้เพียงแค่ใช้ @UninstallModules โดยไม่ต้องใช้โมดูล @TestInstallIn
  • เนื่องจาก Hilt จะสร้าง component ใหม่สำหรับการทดสอบที่ใช้ @UninstallModules ซึ่งอาจส่งผลกระทบรุนแรงต่อ build time ของ unit test ได้ ดังนั้น ควรใช้นานๆ ครั้งและควรใช้ @TestInstallIn เพื่อแทนที่ binding ในทุกคลาสสำหรับการทดสอบจะดีกว่า

วิธีจัดการกับ FragmentScenario

FragmentScenario มี API เพื่อทดสอบยูสเซอร์อินเทอร์เฟซของ fragment ซึ่งมันจะทำงานโดยอัตโนมัติร่วมกับ arbitrary fragment ในทุกเวอร์ชันของ Android framework

มีขั้นตอนบางอย่างที่ต้องทำในการนำ FragmentScenario ไปใช้งาน ดังต่อไปนี้

ขั้นที่ 1: เพิ่ม HiltTestActivity (debug) และ AndroidManifest.xml (debug) ที่ว่างเปล่าเข้าไป

ขั้นที่ 2: ใช้ฟังก์ชันHiltExt พร้อมกับ launchFragmentInHiltContainer extension เพื่อเริ่มการทำงาน fragment ใน container

ขั้นที่ 3:รันการทดสอบได้เลย

คุณกำลังหางาน Android Developer อยู่ใช่ไหม?
ลองดูตำแหน่งงานระดับ Senior, Mid และ Junior Android Developer ของเราก่อน
ดูตำแหน่งงาน