Android tərtibatçısı kimi səyahətimə başlayanda “Mobil Tətbiq Arxitekturası” sözləri məni dərin çaşqınlığa sürüklədi, Google və Habré haqqında məqalələr məni daha da depressiyaya saldı – kitaba baxıram və heç nə görmürəm. Düşünürəm ki, əgər siz bu məqaləni oxuyursunuzsa, siz artıq bu şəkli bir dəfədən çox öyrənmisiniz və nə baş verdiyini anlamağa çalışmısınız: Mobil inkişafda memarlıq yanaşmasını anlamaq problemi, mənim fikrimcə, memarlığın özünün mücərrədliyindədir. Hər bir tərtibatçının bu və ya digər nümunəni necə düzgün həyata keçirəcəyinə dair öz baxışı var. MVP tətbiqinin az-çox layiqli nümunələri İnternetin ingilisdilli sektorunda tapıldı, bu təəccüblü deyil. Nəyin nə olduğuna qısaca nəzər salaq və bir nümunəyə keçək. Model - məlumat səviyyəsi. Mən “biznes məntiqi” terminindən istifadə etməyi sevmirəm, ona görə də tətbiqlərimdə onu Repozitoriya adlandırıram və o, verilənlər bazası və şəbəkə ilə əlaqə saxlayır. Baxış — ekran səviyyəsi. Əgər qavalla rəqs etməyi və həyat dövrü ilə əlaqə saxlamağı sevmirsinizsə, bu Fəaliyyət , Fraqment və ya Xüsusi Görünüş olacaq . Nəzərinizə çatdırım ki, əvvəlcə bütün Android proqramları MVC strukturuna tabedir , burada Nəzarətçi Fəaliyyət və ya Fraqmentdir . Təqdimatçı Görünüş və Model arasında bir təbəqədir. View, baş verən hadisələri ötürür, aparıcı onları emal edir, lazım gələrsə, Modelə daxil olur və məlumatları göstərmək üçün Görünüşə qaytarır. Android və xüsusi bir nümunə ilə əlaqədar olaraq, vacib hissəni - Müqaviləni vurğulayacağam. Bu, yuxarıda göstərilən komponentlər arasındakı bütün qarşılıqlı əlaqəni təsvir edən interfeysdir. Nəzəri hissəni ümumiləşdirmək üçün:
- View Aparıcı haqqında bilir;
- Təqdimatçı Görünüş və Model (Repository) haqqında bilir;
- Özü ilə model;
- Müqavilə onların arasındakı qarşılıqlı əlaqəni tənzimləyir.
MainContract
:
public interface MainContract {
interface View {
void showText();
}
interface Presenter {
void onButtonWasClicked();
void onDestroy();
}
interface Repository {
String loadMessage();
}
}
Hələlik biz sadəcə olaraq gələcək tətbiqimizin 3 komponentini və onların nə edəcəyini vurğulayırıq. Sonra Repozitoriyanı təsvir edəcəyik:
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 "Сосисочная у Лёхи»;
}
}
Bununla hər şey aydındır, sadəcə məlumatların yüklənməsi və boşaldılması. Növbəti aparıcıdır:
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()");
}
}
Dəflə rəqs etmək və həyat dövrü haqqında yazdığımı xatırlayırsanmı? Təqdimatçı Görünüşü yaşadığı müddətcə yaşayır, mürəkkəb istifadəçi ssenariləri hazırlayarkən, mən sizə məsləhət görürəm ki, Təqdimatçıda bütün Baxış geri çağırışlarını təkrarlayın və lazımi məqamlarda onlara zəng edin, Fəaliyyət/Fraqmentin həyat dövrünü təkrarlayın, zamanında nə olduğunu başa düşmək üçün. hal-hazırda "interlayerdə" asılı olan məlumatlarla etmək lazımdır. Və nəhayət, Baxın:
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()");
}
}
Nə baş verir?
- Görünüş kimi tanınan fəaliyyət
onCreate()
metodda Presenter instansiyasını yaradır və özünü onun konstruktoruna ötürür. - Təqdimatçı yaradıldıqda, o, açıq şəkildə Görünüş qəbul edir və Repozitor nümunəsi yaradır (yeri gəlmişkən, onu Singleton etmək olar)
- Düymə basılanda Görünüş aparıcını döyür və deyir: “Düymə basıldı”.
- Təqdimatçı Repozitoriyaya müraciət edir: "Bu axmaqlığı mənim üçün yükləyin."
- Repozitoriya "əşyaları" yükləyir və Təqdimatçıya çatdırır.
- Təqdimatçı Baxışa dönür: “Budur məlumat sizin üçündür, onu çəkin”
GO TO FULL VERSION