คำแนะนำสำหรับสถาปัตยกรรม Android (มุมมอง)

แนวคิดและการใช้งาน Jetpack Compose

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

เลเยอร์ UI

บทบาทของเลเยอร์ UI คือการแสดงข้อมูลแอปพลิเคชันบนหน้าจอ และเป็นจุดหลักของการโต้ตอบของผู้ใช้ แนวทางปฏิบัติแนะนำสำหรับเลเยอร์ UI มีดังนี้

  • คุณควรสร้างที่เก็บแม้ว่าจะมีแหล่งข้อมูลเพียงแหล่งเดียวก็ตาม
  • ในแอปขนาดเล็ก คุณสามารถเลือกวางประเภทเลเยอร์ข้อมูลในdataแพ็กเกจหรือโมดูลได้

คำแนะนำ

คำอธิบาย

ทำตามการไหลของข้อมูลแบบทางเดียว (UDF)

ขอแนะนำ

ปฏิบัติตามหลักการการไหลของข้อมูลแบบทิศทางเดียว (UDF) ซึ่ง ViewModel จะแสดงสถานะ UI โดยใช้รูปแบบ Observer และรับการดำเนินการจาก UI ผ่านการเรียกใช้เมธอด

ใช้ AAC ViewModels หากประโยชน์ของ ViewModel นั้นๆ เหมาะกับแอปของคุณ

ขอแนะนำ

ใช้ AAC ViewModels เพื่อจัดการตรรกะทางธุรกิจ และดึงข้อมูลแอปพลิเคชันเพื่อแสดงสถานะ UI ต่อ UI

ดูแนวทางปฏิบัติแนะนำสำหรับ ViewModel เพิ่มเติมได้ที่นี่

ดูสิทธิประโยชน์ของ ViewModel ได้ที่นี่

ใช้การรวบรวมสถานะ UI ที่รับรู้ถึงวงจร

ขอแนะนำ

รวบรวมสถานะ UI จาก UI โดยใช้ตัวสร้างโครูทีนที่รับรู้ถึงวงจรที่เหมาะสม repeatOnLifecycle

ดูข้อมูลเพิ่มเติมเกี่ยวกับ repeatOnLifecycle

อย่าส่งเหตุการณ์จาก ViewModel ไปยัง UI

ขอแนะนำ

ประมวลผลเหตุการณ์ใน ViewModel ทันทีและทําให้เกิดการอัปเดตสถานะด้วยผลลัพธ์ของการจัดการเหตุการณ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์ UI ที่นี่

ใช้แอปพลิเคชันแบบกิจกรรมเดียว

แนะนำ

ใช้ Navigation Fragments เพื่อไปยังส่วนต่างๆ ของหน้าจอและ Deep Link ไปยังแอปหากแอปมีมากกว่า 1 หน้าจอ

ข้อมูลโค้ดต่อไปนี้แสดงวิธีรวบรวมสถานะ UI ในลักษณะที่รับรู้ถึงวงจร

class MyFragment : Fragment() {

    private val viewModel: MyViewModel by viewModel()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect {
                    // Process item
                }
            }
        }
    }
}

ViewModel

ViewModels มีหน้าที่จัดเตรียมสถานะ UI และการเข้าถึง เลเยอร์ข้อมูล แนวทางปฏิบัติแนะนำบางส่วนสำหรับ ViewModel มีดังนี้

คำแนะนำ

คำอธิบาย

ViewModel ควรไม่ขึ้นอยู่กับวงจรของ Android

ขอแนะนำ

ViewModel ไม่ควรมีการอ้างอิงถึงประเภทที่เกี่ยวข้องกับวงจร อย่าส่ง Activity, Fragment, Context หรือ Resources เป็นทรัพยากร Dependency หากมีบางอย่างที่ต้องใช้ Context ใน ViewModel คุณควรประเมินอย่างรอบคอบว่าอยู่ในเลเยอร์ที่ถูกต้องหรือไม่

ใช้โครูทีนและโฟลว์

ขอแนะนำ

ViewModel จะโต้ตอบกับเลเยอร์ข้อมูลหรือโดเมนโดยใช้สิ่งต่อไปนี้

  • โฟลว์ Kotlin สำหรับรับข้อมูลแอปพลิเคชัน
  • suspend ฟังก์ชันเพื่อดำเนินการโดยใช้ viewModelScope

ใช้ ViewModel ที่ระดับหน้าจอ

ขอแนะนำ

อย่าใช้ ViewModel ในชิ้นส่วน UI ที่นำกลับมาใช้ใหม่ได้ คุณควรใช้ ViewModel ในส่วนต่อไปนี้

  • กิจกรรม/Fragment ในมุมมอง
  • ปลายทางหรือกราฟเมื่อใช้ Jetpack Navigation

อย่าใช้ AndroidViewModel

ขอแนะนำ

ใช้คลาส ViewModel ไม่ใช่ AndroidViewModel ไม่ควรใช้คลาส Application ใน ViewModel แต่ให้ย้ายการอ้างอิงไปยัง UI หรือชั้นข้อมูลแทน

แสดงสถานะ UI

แนะนำ

ViewModel ควรแสดงข้อมูลต่อ UI ผ่านพร็อพเพอร์ตี้เดียวที่ชื่อ uiState หาก UI แสดงข้อมูลหลายรายการที่ไม่เกี่ยวข้อง ViewModel จะแสดงพร็อพเพอร์ตี้สถานะ UI หลายรายการได้

  • คุณควรทำ uiState ให้เป็น StateFlow
  • คุณควรสร้าง uiState โดยใช้โอเปอเรเตอร์ stateIn กับนโยบาย WhileSubscribed(5000) (ตัวอย่าง) หากข้อมูลมาในรูปแบบสตรีมข้อมูลจากเลเยอร์อื่นๆ ของลําดับชั้น
  • ในกรณีที่ง่ายกว่าซึ่งไม่มีสตรีมข้อมูลมาจากชั้นข้อมูล คุณสามารถใช้ MutableStateFlow ที่แสดงเป็น StateFlow ที่เปลี่ยนแปลงไม่ได้
  • คุณเลือกให้ ${Screen}UiState เป็นคลาสข้อมูลที่สามารถมีข้อมูล ข้อผิดพลาด และสัญญาณการโหลดได้ คลาสนี้อาจเป็นคลาสที่ปิดผนึกได้ด้วยหากสถานะต่างๆ เป็นแบบเฉพาะ

ข้อมูลโค้ดต่อไปนี้แสดงวิธีเปิดเผยสถานะ UI จาก ViewModel

@HiltViewModel
class BookmarksViewModel @Inject constructor(
    newsRepository: NewsRepository
) : ViewModel() {

    val feedState: StateFlow<NewsFeedUiState> =
        newsRepository
            .getNewsResourcesStream()
            .mapToFeedState(savedNewsResourcesState)
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5_000),
                initialValue = NewsFeedUiState.Loading
            )

    // ...
}

วงจร

แนวทางปฏิบัติแนะนำสำหรับการทำงานกับวงจร การทำงานของ Android มีดังนี้

คำแนะนำ

คำอธิบาย

อย่าลบล้างเมธอดวงจรในกิจกรรมหรือ Fragment

ขอแนะนำ

อย่าลบล้างเมธอดวงจร เช่น onResume ในกิจกรรมหรือ Fragment โปรดใช้ LifecycleObserver แทน หากแอปต้องทำงานเมื่อวงจรมีสถานะเป็น Lifecycle.State ให้ใช้ repeatOnLifecycle API

ข้อมูลโค้ดต่อไปนี้แสดงวิธีดำเนินการเมื่อมีสถานะ Lifecycle ที่เฉพาะเจาะจง

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onResume(owner: LifecycleOwner) {
                // ...
            }
            override fun onPause(owner: LifecycleOwner) {
                // ...
            }
        }
    }
}