Khi tôi bắt đầu hành trình trở thành một nhà phát triển Android, cụm từ “Kiến trúc ứng dụng di động” đã khiến tôi vô cùng hoang mang, Google và các bài viết về Habré càng khiến tôi chán nản hơn - tôi nhìn vào cuốn sách và chẳng thấy gì cả. Tôi nghĩ nếu bạn đang đọc bài viết này, bạn đã nghiên cứu bức tranh này hơn một lần và cố gắng hiểu điều gì đang xảy ra: Theo tôi, vấn đề hiểu cách tiếp cận kiến trúc trong phát triển di động, nằm ở tính trừu tượng của chính kiến trúc. Mỗi nhà phát triển có tầm nhìn riêng của mình về cách triển khai chính xác mẫu này hoặc mẫu kia. Ít nhiều ví dụ điển hình về việc triển khai MVP đã được tìm thấy trong khu vực nói tiếng Anh trên Internet, điều này không có gì đáng ngạc nhiên. Chúng ta hãy xem xét ngắn gọn những gì là những gì và chuyển sang một ví dụ. Mô hình - mức dữ liệu. Tôi không thích sử dụng thuật ngữ “logic nghiệp vụ”, vì vậy trong các ứng dụng của mình, tôi gọi nó là Kho lưu trữ và nó giao tiếp với cơ sở dữ liệu và mạng. Xem - mức độ hiển thị. Đó sẽ là Hoạt động , Đoạn hoặc Chế độ xem tùy chỉnh nếu bạn không thích nhảy múa với tambourine và tương tác với vòng đời. Hãy để tôi nhắc bạn rằng ban đầu tất cả các ứng dụng Android đều phụ thuộc vào cấu trúc MVC , trong đó Bộ điều khiển là Hoạt động hoặc Đoạn . Presenter là một lớp giữa View và Model. Chế độ xem truyền các sự kiện xảy ra với nó, người trình bày sẽ xử lý chúng, nếu cần, truy cập vào Mô hình và trả về dữ liệu cho Chế độ xem để hiển thị. Liên quan đến Android và một ví dụ cụ thể, tôi sẽ nêu bật phần quan trọng - Hợp đồng. Đây là giao diện mô tả tất cả các tương tác giữa các thành phần trên. Tóm tắt phần lý thuyết:
- Xem biết về Người trình bày;
- Người trình bày biết về Chế độ xem và Mô hình (Kho lưu trữ);
- Tự làm mẫu;
- Hợp đồng chi phối sự tương tác giữa chúng.
MainContract
:
public interface MainContract {
interface View {
void showText();
}
interface Presenter {
void onButtonWasClicked();
void onDestroy();
}
interface Repository {
String loadMessage();
}
}
Hiện tại, chúng tôi chỉ nêu bật 3 thành phần của ứng dụng trong tương lai và chức năng của chúng. Tiếp theo chúng ta sẽ mô tả Kho lưu trữ:
public class MainRepository implements MainContract.Repository {
private static final String TAG = "MainRepository";
@Override
public String loadMessage() {
Log.d(TAG, "loadMessage()");
/** Здесь обращаемся к БД or сети.
* Я специально ничего не пишу, чтобы не загромождать пример
* DBHelper'ами и прочими не относяшимеся к теме an objectми.
* Поэтому я буду возвращать строку Сосисочная =)
*/
return "Сосисочная у Лёхи»;
}
}
Mọi thứ đều rõ ràng với nó, chỉ cần tải và dỡ dữ liệu. Tiếp theo là Người trình bày:
public class MainPresenter implements MainContract.Presenter {
private static final String TAG = "MainPresenter";
//Компоненты MVP applications
private MainContract.View mView;
private MainContract.Repository mRepository;
//Сообщение
private String message;
//Обрати внимание на аргументы конструктора - мы передаем экземпляр View, а Repository просто создаём конструктором.
public MainPresenter(MainContract.View mView) {
this.mView = mView;
this.mRepository = new MainRepository();
Log.d(TAG, "Constructor");
}
//View сообщает, что кнопка была нажата
@Override
public void onButtonWasClicked() {
message = mRepository.loadMessage();
mView.showText(message);
Log.d(TAG, "onButtonWasClicked()");
}
@Override
public void onDestroy() {
/**
* Если бы мы работали например с RxJava, в этом классе стоило бы отписываться от подписок
* Кроме того, при работе с другими методами асинхронного андроида,здесь мы боремся с утечкой контекста
*/
Log.d(TAG, "onDestroy()");
}
}
Bạn có nhớ tôi đã viết về việc khiêu vũ với trống lục lạc và vòng đời không? Trình trình bày tồn tại miễn là Chế độ xem của nó tồn tại, khi phát triển các kịch bản người dùng phức tạp, tôi khuyên bạn nên sao chép tất cả lệnh gọi lại Chế độ xem trong Trình bày và gọi chúng vào những thời điểm thích hợp, sao chép vòng đời Hoạt động/Phân đoạn, để hiểu kịp thời những gì cần được thực hiện với dữ liệu hiện đang treo trong “lớp xen kẽ”. Và cuối cùng, Xem:
public class MainActivity extends AppCompatActivity implements MainContract.View {
private static final String TAG = "MainActivity";
private MainContract.Presenter mPresenter;
private Button mButton;
private TextView myTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Создаём Presenter и в аргументе передаём ему this - эта Activity расширяет интерфейс MainContract.View
mPresenter = new MainPresenter(this);
myTv = (TextView) findViewById(R.id.text_view);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.onButtonWasClicked();
}
});
Log.d(TAG, "onCreate()");
}
@Override
public void showText(String message) {
myTv.setText(message);
Log.d(TAG, "showMessage()");
}
//Вызываем у Presenter метод onDestroy, чтобы избежать утечек контекста и прочих неприятностей.
@Override
public void onDestroy() {
super.onDestroy();
mPresenter.onDestroy();
Log.d(TAG, "onDestroy()");
}
}
Chuyện gì đang xảy ra vậy?
- Hoạt động, còn được gọi là Chế độ xem,
onCreate()
tạo một phiên bản Trình bày trong một phương thức và chuyển chính nó tới hàm tạo của nó. - Khi Người trình bày được tạo, nó sẽ nhận một Chế độ xem một cách rõ ràng và tạo một phiên bản Kho lưu trữ (nhân tiện, nó có thể được tạo thành Singleton)
- Khi nhấn một nút, Chế độ xem sẽ gõ vào người trình bày và thông báo: “Nút đã được nhấn”.
- Người trình bày quay sang Kho lưu trữ: “Tải xuống cái thứ nhảm nhí này cho tôi.”
- Kho lưu trữ tải và phân phối “nội dung” cho Người trình bày.
- Người thuyết trình quay sang View: “Đây là dữ liệu cho bạn, hãy vẽ nó”
GO TO FULL VERSION