안드로이드 개발자로서의 여정을 시작했을 때 "모바일 애플리케이션 아키텍처"라는 단어는 나에게 깊은 당혹감을 안겨 주었고, Google과 Habré에 관한 기사는 나를 더욱 큰 우울증에 빠뜨렸습니다. 책을 보지만 아무 것도 볼 수 없습니다. 이 기사를 읽고 계시다면 이미 이 그림을 한 번 이상 연구하고 무슨 일이 일어나고 있는지 이해하려고 노력하셨을 것입니다. 제 생각에는 모바일 개발에서 아키텍처 접근 방식을 이해하는 문제는 아키텍처 자체의 추상성에 있습니다. 각 개발자는 특정 패턴을 올바르게 구현하는 방법에 대한 자신의 비전을 가지고 있습니다. MVP 구현의 다소 괜찮은 예가 인터넷의 영어권 부문에서 발견되었는데 이는 놀라운 일이 아닙니다. 무엇이 무엇인지 간략하게 살펴보고 예제로 넘어 갑시다. 모델 - 데이터 수준. 나는 "비즈니스 로직"이라는 용어를 사용하는 것을 좋아하지 않기 때문에 내 애플리케이션에서는 이를 저장소라고 부르며 데이터베이스 및 네트워크와 통신합니다. 보기 - 표시 수준. 탬버린과 함께 춤추고 라이프 사이클과 상호작용하는 것을 좋아하지 않는다면 Activity , Fragment 또는 Custom View 가 될 것입니다 . 처음에 모든 Android 애플리케이션은 컨트롤러가 활동 또는 조각인 MVC 구조 에 종속 된다는 점을 상기시켜 드리겠습니다 . Presenter 는 View와 Model 사이의 레이어입니다. View는 발생하는 이벤트를 전송하고, Presenter는 이를 처리하며, 필요한 경우 Model에 액세스하고 렌더링을 위해 데이터를 View에 반환합니다. Android 및 구체적인 예와 관련하여 중요한 부분인 계약을 강조하겠습니다. 위의 구성 요소 간의 모든 상호 작용을 설명하는 인터페이스입니다. 이론적 부분을 요약하면 다음과 같습니다.
- View는 Presenter에 대해 알고 있습니다.
- 발표자는 View 및 Model(Repository)에 대해 알고 있습니다.
- 그 자체로 모델;
- 계약은 그들 사이의 상호 작용을 관리합니다.
MainContract
.
public interface MainContract {
interface View {
void showText();
}
interface Presenter {
void onButtonWasClicked();
void onDestroy();
}
interface Repository {
String loadMessage();
}
}
지금은 미래 애플리케이션의 3가지 구성 요소와 그 기능을 강조하는 것뿐입니다. 다음으로 리포지토리에 대해 설명하겠습니다.
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 "Сосисочная у Лёхи»;
}
}
데이터를 로드하고 언로드하기만 하면 모든 것이 명확해집니다. 다음은 발표자입니다.
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()");
}
}
제가 탬버린과 함께 춤을 추는 것과 생활주기에 대해 쓴 것을 기억하시나요? Presenter는 View가 작동하는 동안 지속됩니다. 복잡한 사용자 시나리오를 개발할 때 Presenter에서 모든 View 콜백을 복제하고 적절한 순간에 호출하여 Activity/Fragment 수명 주기를 복제하여 무엇이 필요한지 제때 이해하는 것이 좋습니다. 현재 "중간층"에 걸려 있는 데이터를 처리해야 합니다. 마지막으로 보기:
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()");
}
}
무슨 일이야?
- View라고도 알려진 Activity는
onCreate()
메서드에서 Presenter 인스턴스를 생성하고 생성자에 자신을 전달합니다. - Presenter가 생성되면 명시적으로 View를 수신하고 Repository 인스턴스를 생성합니다(단, 싱글톤으로 만들 수도 있음).
- 버튼을 누르면 View가 발표자를 두드리며 "버튼을 눌렀습니다."라고 말합니다.
- 발표자는 저장소로 이동합니다. "이 쓰레기를 다운로드해 주세요."
- 저장소는 "물건"을 로드하고 발표자에게 전달합니다.
- 발표자는 보기로 전환합니다. "여기에 데이터가 있습니다. 그려보세요."
GO TO FULL VERSION