Các khái niệm và cách triển khai Jetpack Compose
Trang này trình bày một số nội dung đề xuất và phương pháp hay nhất về cấu trúc. Hãy áp dụng các nội dung đề xuất đó để cải thiện chất lượng, độ mạnh và khả năng mở rộng của ứng dụng. Các nội dung đề xuất này cũng giúp bạn bảo trì và kiểm thử ứng dụng dễ dàng hơn.
Lớp giao diện người dùng
Vai trò của lớp giao diện người dùng là hiển thị dữ liệu ứng dụng trên màn hình và đóng vai trò là điểm chính trong quá trình tương tác của người dùng. Dưới đây là một số phương pháp hay nhất cho lớp giao diện người dùng:
- Bạn nên tạo các kho lưu trữ ngay cả khi chúng chỉ chứa một nguồn dữ liệu duy nhất.
- Trong ứng dụng nhỏ, bạn có thể chọn đặt các loại lớp dữ liệu vào gói hoặc mô-đun
data.
Nội dung đề xuất |
Nội dung mô tả |
Tuân theo nguyên tắc Luồng dữ liệu một chiều (UDF). Rất nên dùng |
Tuân theo nguyên tắc Luồng dữ liệu một chiều (UDF), trong đó ViewModel hiển thị trạng thái giao diện người dùng thông qua mẫu trình quan sát và nhận các thao tác từ giao diện người dùng thông qua lệnh gọi phương thức. |
Dùng ViewModel AAC nếu có lợi cho ứng dụng của bạn. Rất nên dùng |
Dùng AAC ViewModels để xử lý logic kinh doanh, cũng như tìm nạp dữ liệu ứng dụng để hiển thị trạng thái giao diện người dùng cho giao diện người dùng. |
Dùng bộ sưu tập trạng thái giao diện người dùng có nhận biết vòng đời. Rất nên dùng |
Thu thập trạng thái giao diện người dùng từ giao diện người dùng bằng trình tạo coroutine có nhận biết vòng đời thích hợp, Đọc thêm về |
Không gửi các sự kiện từ ViewModel đến giao diện người dùng. Rất nên dùng |
Xử lý sự kiện ngay lập tức trong ViewModel và cập nhật trạng thái bằng kết quả xử lý sự kiện. Tìm hiểu thêm về sự kiện giao diện người dùng tại đây. |
Dùng ứng dụng hoạt động đơn. Đề xuất |
Dùng Mảnh điều hướng để di chuyển giữa các màn hình và liên kết sâu đến ứng dụng của bạn nếu ứng dụng có nhiều màn hình. |
Đoạn mã sau đây chỉ ra cách thu thập trạng thái giao diện người dùng theo cách có nhận biết vòng đời:
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
ViewModel chịu trách nhiệm cung cấp trạng thái giao diện người dùng và quyền truy cập vào lớp dữ liệu. Dưới đây là một số phương pháp hay nhất về ViewModel:
Nội dung đề xuất |
Nội dung mô tả |
ViewModel phải độc lập với vòng đời của Android. Rất nên dùng |
ViewModel không được chứa tệp tham chiếu đến bất kỳ kiểu nào liên quan đến Vòng đời. Không truyền |
Dùng coroutine và luồng. Rất nên dùng |
ViewModel tương tác với các lớp dữ liệu hoặc miền thông qua:
|
Dùng ViewModel ở cấp màn hình. Rất nên dùng |
Không sử dụng ViewModel trong các phần giao diện người dùng có thể tái sử dụng. Bạn nên sử dụng ViewModel trong:
|
Không sử dụng Rất nên dùng |
Dùng lớp |
Hiển thị trạng thái giao diện người dùng. Đề xuất |
ViewModel phải hiển thị dữ liệu cho giao diện người dùng thông qua một thuộc tính có tên là
|
Đoạn mã sau đây trình bày cách hiển thị trạng thái giao diện người dùng từ 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
)
// ...
}
Vòng đời
Sau đây là một số phương pháp hay nhất để xử lý vòng đời của Android:
Nội dung đề xuất |
Nội dung mô tả |
Không ghi đè các phương thức vòng đời trong Activity (Hoạt động) hoặc Fragment (Mảnh). Rất nên dùng |
Không ghi đè các phương thức vòng đời, chẳng hạn như |
Đoạn mã sau đây trình bày cách thực hiện các thao tác dựa trên một trạng thái Vòng đời nhất định:
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) {
// ...
}
}
}
}