Мен Android әзірлеушісі ретінде саяхатымды бастаған кезде, «Мобильдік қолданбалар архитектурасы» деген сөздер мені қатты таң қалдырды, Google және Хабре туралы мақалалар мені одан да қатты депрессияға ұшыратты - мен кітапқа қарап, ештеңе көрмеймін. Менің ойымша, егер сіз осы мақаланы оқып жатсаңыз, сіз бұл суретті бірнеше рет зерттеп, не болып жатқанын түсінуге тырыстыңыз: Мобильді дамудағы архитектуралық тәсілді түсіну мәселесі, менің ойымша, сәулеттің абстрактілілігінде жатыр. Әрбір әзірлеушінің осы немесе басқа үлгіні қалай дұрыс жүзеге асыруға болатыны туралы өз көзқарасы бар. Интернеттің ағылшын тілді секторында MVP енгізудің азды-көпті лайықты мысалдары табылды, бұл таңқаларлық емес. Ненің не екенін қысқаша қарастырып, мысалға көшейік. Модель – деректер деңгейі. Мен «бизнес логикасы» терминін пайдаланғанды ұнатпаймын, сондықтан менің қолданбаларымда мен оны Репозиторий деп атаймын және ол дерекқормен және желімен байланысады. Көрініс — дисплей деңгейі. Егер сіз бубен билегенді және өмірлік циклмен әрекеттесуді ұнатпасаңыз, бұл Activity , Fragment немесе Custom View болады . Естеріңізге сала кетейін, бастапқыда барлық Android қолданбалары MVC құрылымына бағынады , мұнда контроллер әрекет немесе фрагмент болып табылады . Баяндамашы – Көрініс пен Үлгі арасындағы қабат. Көрініс оған орын алған оқиғаларды жібереді, баяндамашы оларды өңдейді, қажет болса, Үлгіге қол жеткізеді және деректерді көрсету үшін Көрініске қайтарады. Android-ге және нақты мысалға қатысты мен маңызды бөлікті - Келісімшартты бөліп көрсетемін. Бұл жоғарыда аталған компоненттер арасындағы барлық өзара әрекеттесуді сипаттайтын интерфейс. Теориялық бөлімді қорытындылау үшін:
- Көрініс Жүргізуші туралы біледі;
- Баяндамашы Көрініс және Үлгі (Репозиторий) туралы біледі;
- Өздігінен үлгі;
- Шарт олардың арасындағы өзара әрекетті реттейді.
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()");
}
}
Дабылмен билеу және өмірлік цикл туралы жазғаным есіңізде ме? Баяндамашы өзінің Көрінісінің өмір сүретін уақытында өмір сүреді, күрделі пайдаланушы сценарийлерін жасағанда, мен сізге Презентациядағы барлық Көрініс кері шақыруларының көшірмесін жасауға және оларды уақытында түсіну үшін Әрекет/Фрагменттің өмірлік циклін қайталай отырып, тиісті сәттерде қоңырау шалуға кеңес беремін. қазіргі уақытта «аралық қабатта» ілулі тұрған деректермен орындалуы керек. Соңында, қараңыз:
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()");
}
}
Не болып жатыр?
- Көрініс деп те белгілі әрекет
onCreate()
әдісте Presenter данасын жасайды және өзін оның конструкторына береді. - Баяндамашы жасалғанда, ол анық Көрініс алады және репозиторий данасын жасайды (айтпақшы, оны Singleton жасауға болады)
- Түйме басылғанда, Көрініс баяндамашыны қағып: «Түйме басылды» дейді.
- Жүргізуші репозиторийге бұрылады: «Маған мына сұмдықты жүктеп алыңыз».
- Репозиторий «заттарды» жүктеп, Баяндамашыға жеткізеді.
- Баяндамашы Көрініске бұрылады: «Міне, сіз үшін деректер, оны сызыңыз»
GO TO FULL VERSION