Ví dụ Clean Architecture trong Android

Clean Architecture, một design pattern ngày càng phổ biến và sử dụng rộng rãi trong Android. Và chúng ta sẽ đi thẳng vào ví dụ, để hiểu rõ hơn về design pattern này.

Trước hết, tôi xin nhắc lại ưu điẻm của Clean Architecture pattern:

  • Độc lập với các framework.
  • Testable.
  • Đôcc lập với UI.
  • Độc lập với database.
  • Độc lập với bất kỳ external agent nào khác.
  1. Tổng quan

Ví dụ sẽ được tách làm 3 package : presentation, storage, domain.

2 package đầu thuộc về outer layer và package cuối cùng sẽ là inner/core layer.

Package Presentation chịu trách nhiệm cho tất cả mọi thứ liên quan đến việc hiển thị trên màn hình – nó bao gồm toàn bộ MVP stack (có nghĩa là nó cũng bao gồm cả các giao diện người dùng và các package Presenter mặc dù chúng thuộc các layer khác nhau).

  1. Tạo một Interactor mới (inner/core layer)

Bạn có thể bắt đầu từ bất kỳ layer nào của architecture, nhưng lời khuyên là nên bắt đầu từ logic core business đầu tiên. Bạn có thể code, test, và chắc rằng nó hoạt động mà không cần đến activity.

Vì vậy, chúng ta hãy bắt đầu bằng cách tạo ra một INteractor. Các INteractor là nơi logic chính của các use case cư trú. Tất cả Interactors đang chạy trong thread nền vì vậy không nên có bất kỳ ảnh hưởng đến hiệu suất UI. Hãy tạo ra một INteractor mới với tên WelcomingInteractor.

Callback sẽ trách nhiệm giao tiếp với UI trên các main thread, đặt nó vào giao diện của INteractor này vì vậy không cần phải đặt tên cho nó là WelcomingInteractorCallback – để phân biệt nó từ callbacks khác. Bây giờ chúng ta hãy thực hiện logic lấy một tin nhắn. Chúng ta có một MessageRepository có thể cung cấp các welcome message.

Bây giờ hãy implement giao diện INteractor business logic trên. Điều quan trọng là implement extend của AbstractInteractor và chú ý tới việc chạy trên background thread.

Điều này chỉ cố gắng để tải message và gửi message hoặc hiển thị các lỗi UI. Chúng ta xác định UI thông qua callback mà sẽ được thực hiện ở Presenter. Đó là mấu chốt của business logic ở đay. Tất cả mọi thứ mà chúng ta cần làm là framework dependence.

Dưới đây là 1 số phụ thuộc mà Interactor này có:

Như bạn có thể thấy, ở đây không đề cập đến bất kỳ code Android nào. Đó là lợi ích chính của phương pháp này. Bạn có thể thấy được sự độc lập của framework. Ngoài ra, chúng ta không quan tâm đến chi tiết cụ thể của UI hoặc db, chúng ta chỉ cần gọi interface mà ở đâu đó outer layer sẽ implement. Do đó, chúng ta có sự độc lập về UI và db.

Bây giờ chúng ta có thể run và test Interactor không cần chạy emulator. Vì vậy, chúng ta hãy viết một test JUnit đơn giản để đảm bảo nó hoạt động:

Một lần nữa, code Interactor này không có ý tưởng rằng nó sẽ sống bên trong một ứng dụng Android. Điều này chứng tỏ rằng business logic ở đây là Testable, đó là điểm thứ hai để thấy.

  1. Tạo presenter layer

Code Presenter thuộc outer layer trong Clean. Nó bao gồm các code phụ thuộc vào framework để hiển thị UI cho người dùng. Chúng ta sẽ sử dụng lớp MainActivity để hiển thị welcome message cho người sử dụng khi ứng dụng resume.

Vì vậy, làm thế nào và nơi nào chúng ta bắt đầu Interactor khi một ứng dụng resume? Tất cả mọi thứ mà liên quan đến stritly nên cho vào các lớp Presenter. Điều này giúp tách các mối quan hệ và ngăn ngừa các class Hoạt động cồng kềnh. Điều này bao gồm tất cả các code làm việc với Interactors.

Trong onResume của Mainactivity, chúng ta nên override hàm onResume():

Tất cả Presenter object implement hàm resume() khi chúng extend từ BasePresenter.

Chúng ta start Interactor bên trong MainPresenter class trong hàm resume() :

Hàm execute() sẽ chạy hàm run() của WelcomingInteractorImpl bên trong background thread. Hàm run() có thể được thấy khi viết một Interactor mới.

MainPresenter của MainActivity sẽ implement Callback interface:

Đó là cách chúng ta lắng nghe sự kiện từ Interator. Và đây là code từ MainPresenter:

Và MainActivity cũng se implement interface View của MainPresenter.

  1. Tạo một storage layer

Đây là nơi respository được implement. Tất cả các code cụ thể của cơ sở dữ liệu nên ở đây. Các repository pattern chỉ abstract nơi dữ liệu đến từ đâu. Business logic chính ở đây là không biết gì về nguồn gốc của dữ liệu – có thể là từ một cơ sở dữ liệu, máy chủ hoặc các tập tin văn bản.

Đối với dữ liệu phức tạp, bạn có thể sử dụng ContentProviders hoặc các công cụ ORM như DBFlow. Nếu cần phải lấy dữ liệu từ các trang web, Retrofit sẽ giúp bạn. Nếu cần lưu trữ giá trị đơn giản, có thể sử dụng SharedPreferences. Nên sử dụng đúng công cụ cho từng công việc.

Database ở đây không hẳn là một database. Nó chỉ đơn giản là một class với một sự mô phong delay:

Chúng ta không cần quan tâm đến những gì là dưới MessageRepository miễn là nó thực hiện đúng giao diện.

  1. Tổng kết

Quy trình hoạt ddoognj của Clean Architecture sẽ như sau:
MainActivity ->MainPresenter -> WelcomingInteractor -> WelcomeMessageRepository -> WelcomingInteractor -> MainPresenter -> MainActivity

  • Điều quan trọng cần nhớ về flow control:
    Outer — Mid — Core — Outer — Core — Mid — Outer.

Nhận xét