
Khai tử BaseFragment: Xây dựng màn hình tái sử dụng thực thụ trong Jetpack Compose
Hướng dẫn chi tiết cách loại bỏ tư duy BaseFragment cũ kỹ để chuyển sang kiến trúc Compose hiện đại, giúp code sạch hơn, dễ bảo trì và tái sử dụng cao.
Bài viết được dịch và tổng hợp từ tin tức gốc. Bạn có thể đọc bài viết gốc bằng tiếng Anh tại đây.
Điểm tin nhanh:
- Thay thế BaseFragment bằng các Composable wrapper chuyên biệt để xử lý cross-cutting concerns.
- Sử dụng CompositionLocal để quản lý dependency thay vì truyền prop thủ công qua nhiều tầng.
- Tận dụng LaunchedEffect và Channel để xử lý các sự kiện một lần (one-time events) một cách an toàn.
Trong kỷ nguyên của View-based Android, BaseFragment là cứu cánh để tránh lặp lại code. Tuy nhiên, khi chuyển sang Jetpack Compose, việc cố gắng áp dụng mô hình kế thừa này không chỉ lỗi thời mà còn tạo ra những rào cản kỹ thuật không đáng có. Đã đến lúc chúng ta cần một tư duy mới: thay vì kế thừa, hãy sử dụng sự kết hợp (composition) để xây dựng những màn hình linh hoạt, dễ bảo trì và chuẩn chỉnh hơn.
Pattern 1: BaseScreen Composable - Thay thế cho BaseFragment
Thay vì một lớp cha cồng kềnh, hãy sử dụng một Higher-order Composable để bao bọc các logic chung như trạng thái loading hoặc lỗi. Điều này giúp code của bạn trở nên surgical (chính xác) hơn.
@Composable
fun BaseScreen(
uiState: UiState,
modifier: Modifier = Modifier,
onRetry: (() -> Unit)? = null,
content: @Composable () -> Unit
) {
Box(modifier = modifier.fillMaxSize()) {
when {
uiState.isLoading -> FullScreenLoader()
uiState.error != null -> ErrorScreen(message = uiState.error, onRetry = onRetry)
else -> content()
}
}
}
Việc áp dụng mô hình này giúp bạn dễ dàng đồng bộ giao diện toàn ứng dụng. Nếu bạn đang gặp khó khăn trong việc quản lý chi phí phát triển khi dự án phình to, hãy tham khảo thêm bài viết về tối ưu hóa chi phí phát triển để có cái nhìn tổng quan hơn về quản trị tài nguyên.

Pattern 2: ScaffoldScreen và cấu trúc App Chrome
Thay vì cấu hình Scaffold ở mỗi màn hình, hãy tạo một wrapper chấp nhận cấu hình (configuration). Điều này giúp các màn hình chỉ tập trung vào mô tả nội dung thay vì cách xây dựng khung giao diện.
Mẹo hay: Hãy định nghĩa một data class
ScreenConfigđể quản lý trạng thái của TopBar, FAB và các thành phần điều hướng một cách tập trung.
Pattern 3: Composable và ViewModel Contract
Đừng lạm dụng BaseViewModel. Thay vào đó, hãy sử dụng Interface để định nghĩa contract. Cách tiếp cận này tương tự như cách chúng ta tối ưu hóa quy trình kỹ thuật bằng các module tái sử dụng trong DevOps.
| Đặc điểm | BaseFragment Pattern | Compose Equivalent |
|---|---|---|
| Cấu trúc | abstract class BaseFragment | @Composable BaseScreen |
| Logic chung | abstract class BaseViewModel | AppViewModel Interface |
| Điều hướng | setupToolbar() | ScaffoldScreen config |
| Sự kiện | observe(events) | HandleEvents Composable |
Pattern 4: CompositionLocal cho Dependency Injection
CompositionLocal là giải pháp hoàn hảo để tránh prop drilling. Nó cho phép bạn inject các thành phần như Analytics, Navigator hay Feature Flags vào cây UI mà không cần truyền qua từng hàm.

Pattern 5: Xử lý sự kiện một lần (One-time Events)
Trong Compose, việc xử lý Toast hoặc điều hướng cần sự cẩn trọng. Sử dụng LaunchedEffect kết hợp với Channel là cách tiếp cận chuẩn mực để đảm bảo sự kiện chỉ được tiêu thụ một lần, tránh các lỗi trạng thái không mong muốn.
Đánh giá & Lời khuyên Thực tiễn
Từ góc nhìn của một Senior Tech Lead, việc loại bỏ BaseFragment là bước đi tất yếu để hiện đại hóa codebase.
- Ưu điểm: Code sạch, dễ test, tính tái sử dụng cao, tránh được các vấn đề về lifecycle phức tạp của Fragment.
- Nhược điểm: Đòi hỏi tư duy thiết kế hệ thống tốt hơn, dễ rơi vào bẫy lạm dụng CompositionLocal nếu không kiểm soát chặt chẽ.
- Lưu ý: Đừng cố gắng làm cho
BaseScreentrở nên quá thông minh. Nếu bạn bắt đầu thêm các logic như kiểm tra quyền truy cập hay xác thực vào đây, bạn đang vô tình xây dựng lại một BaseFragment phiên bản mới. Hãy giữ nó đơn giản.
Nếu bạn đang xây dựng các hệ thống phức tạp, việc nắm vững kỹ thuật viết Unit Test trong Python cũng sẽ giúp bạn có tư duy tốt hơn về việc tách biệt logic trong Android.
Câu hỏi thường gặp (FAQ)
Tại sao không nên dùng BaseFragment trong Compose?
Vì Compose dựa trên cơ chế Composition (kết hợp) thay vì Inheritance (kế thừa). BaseFragment ép buộc bạn vào một cấu trúc cứng nhắc, trong khi Compose khuyến khích sự linh hoạt.
Làm sao để tránh prop drilling khi không dùng BaseFragment?
Sử dụng CompositionLocal để cung cấp các dependency toàn cục hoặc sử dụng các state holder (rememberX) để quản lý trạng thái cục bộ.
Có nên dùng chung một BaseViewModel cho toàn bộ app không?
Không nên. Hãy dùng Interface để định nghĩa contract chung, sau đó implement vào các ViewModel cụ thể để đảm bảo tính phân tách trách nhiệm (Separation of Concerns).
Kết luận
Việc chuyển đổi từ BaseFragment sang các mô hình Composable tái sử dụng là một hành trình nâng cấp tư duy lập trình. Hãy bắt đầu bằng việc refactor các màn hình đơn giản nhất, sau đó áp dụng dần các pattern về ScaffoldScreen và CompositionLocal. Nếu bạn muốn tìm hiểu thêm về cách tối ưu hóa các quy trình khác, hãy theo dõi hi_dev để cập nhật những kiến thức chuyên sâu nhất.
Do you like this post?
Upvote to push this post higher on the community feed




