JavaRush /Java blogi /Random-UZ /Kichkintoylar uchun Androidda MVP

Kichkintoylar uchun Androidda MVP

Guruhda nashr etilgan
Men Android dasturchisi sifatida sayohatimni boshlaganimda, "Mobil ilovalar arxitekturasi" so'zlari meni chuqur hayratda qoldirdi, Google va Habré haqidagi maqolalar meni yanada qattiq tushkunlikka soldi - men kitobga qarayman va hech narsani ko'rmayapman. O'ylaymanki, agar siz ushbu maqolani o'qiyotgan bo'lsangiz, siz ushbu rasmni bir necha marta o'rganib chiqdingiz va nima sodir bo'layotganini tushunishga harakat qildingiz: Kichkintoylar uchun Androidda MVP - 1Mobil rivojlanishda me'moriy yondashuvni tushunish muammosi, menimcha, arxitekturaning mavhumligida yotadi. Har bir ishlab chiquvchining u yoki bu naqshni qanday qilib to'g'ri amalga oshirish haqida o'z qarashlari bor. MVPni amalga oshirishning ko'proq yoki kamroq munosib misollari Internetning ingliz tilida so'zlashuvchi sektorida topilgan, bu ajablanarli emas. Keling, nima ekanligini qisqacha ko'rib chiqamiz va misolga o'tamiz. Model - ma'lumotlar darajasi. Men "biznes mantig'i" atamasini ishlatishni yoqtirmayman, shuning uchun o'z ilovalarimda uni Repository deb atayman va u ma'lumotlar bazasi va tarmoq bilan aloqa qiladi. Ko‘rish — displey darajasi. Agar siz daf bilan raqsga tushishni va hayot tsikli bilan o'zaro munosabatda bo'lishni yoqtirmasangiz, bu Faoliyat , Fragment yoki Maxsus ko'rinish bo'ladi . Eslatib o'taman, dastlab barcha Android ilovalari MVC tuzilishiga bo'ysunadi , bu erda Controller Faoliyat yoki Fragment hisoblanadi . Taqdimotchi - View va Model o'rtasidagi qatlam. View o'zida sodir bo'lgan voqealarni uzatadi, taqdimotchi ularni qayta ishlaydi, agar kerak bo'lsa, Modelga kiradi va ma'lumotlarni ko'rsatish uchun Ko'rinishga qaytaradi. Android va aniq bir misol bilan bog'liq holda, men muhim qismni - Shartnomani ta'kidlayman. Bu yuqoridagi komponentlar orasidagi barcha o'zaro aloqalarni tavsiflovchi interfeys. Nazariy qismni umumlashtirish uchun:
  • View Presenter haqida biladi;
  • Taqdimotchi View va Model (Repository) haqida biladi;
  • O'z-o'zidan model;
  • Shartnoma ular o'rtasidagi o'zaro munosabatlarni tartibga soladi.
Aslida, misolning o'zi, tajribaning soddaligi uchun tugmani bosish orqali biz ma'lumotlar bazasidan qatorni yuklaymiz va uni TextView-da ko'rsatamiz . Misol uchun, ma'lumotlar bazasida shaharning eng yaxshi restoranlari ro'yxati mavjud. Keling, shartnomadan boshlaylik: Keling, interfeys yarataylik MainContract:
public interface MainContract {
    interface View {
        void showText();
    }

    interface Presenter {
        void onButtonWasClicked();
        void onDestroy();
    }

    interface Repository {
        String loadMessage();
    }
}
Hozircha biz kelajakdagi ilovamizning 3 komponentini va ular nima qilishini ta'kidlaymiz. Keyin biz omborni tasvirlaymiz:
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 "Сосисочная у Лёхи»;
    }
}
U bilan hamma narsa aniq, faqat ma'lumotlarni yuklash va tushirish. Keyingisi Taqdimotchi:
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()");
    }
}
Men daf bilan raqsga tushish va hayot aylanishi haqida yozganimni eslaysizmi? Taqdimotchi o'z View umri davomida yashaydi, murakkab foydalanuvchi stsenariylarini ishlab chiqayotganda, men sizga Presenterdagi barcha View qayta qo'ng'iroqlarini takrorlashni maslahat beraman va ularni o'z vaqtida tushunish uchun Faoliyat/Fragmentning hayot aylanishini takrorlab, tegishli daqiqalarda qo'ng'iroq qiling. hozirda "interlayer" da osilgan ma'lumotlar bilan bajarilishi kerak. Va nihoyat, Ko'rish:
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()");
    }
}
Nima gaplar?
  • Faoliyat, shuningdek, View sifatida ham tanilgan, onCreate()usulda Presenter misolini yaratadi va o'zini uning konstruktoriga o'tkazadi.
  • Taqdimotchi yaratilganda, u aniq ko'rinishni oladi va Repository misolini yaratadi (aytmoqchi, uni Singleton qilish mumkin)
  • Tugma bosilganda, View taqdimotchini taqillatadi va "tugma bosildi" deb aytadi.
  • Taqdimotchi omborga murojaat qiladi: "Men uchun bu axlatni yuklab oling."
  • Repozitariy "narsalarni" yuklaydi va Taqdimotchiga etkazib beradi.
  • Taqdimotchi Ko'rishga o'girilib: "Mana siz uchun ma'lumotlar, uni chizing"
Mana, yigitlar. PS Komponentlar o'rtasidagi mas'uliyatni aniq belgilash muhimdir. Misol uchun, mening o'quv loyihalarimdan birida, tugmani bosganingizda, ma'lumotlar bazasidagi ma'lumotlarni o'zgartirish kerak edi. Model POJO klassi tomonidan tasvirlangan, men ekrandagi ob'ekt haqida ma'lumot uchun mas'ul bo'lgan ko'rinishning joylashuvi haqida ma'lumot berdim, Taqdimotchi ushbu ob'ektni ro'yxatda qidirdi va uni omborga yozish uchun yubordi. Hammasi mantiqiy ko'rinadimi? Ammo mening ustozim quyidagilarni ta'kidladi: Repozitariy FAQAT yozish va o'qish bilan shug'ullanishi kerak, u POJOdan kerakli ma'lumotlarni chiqarib tashlamasligi va nima yozish kerakligini hal qilishi kerak. Taqdimotchi unga faqat yozib olish uchun ma'lumot berishi kerak va boshqa hech narsa yo'q. Arxitekturani amalga oshirish uchun qat'iy asos yo'q: tajriba qiling, sinab ko'ring, shaxsan sizga mos keladigan narsani qidiring. Kodni ko'rib chiqishda katta o'rtoqlaringizni ko'rsatishni unutmang =) Misol GitHub-da mavjud: https://github.com/admitrevskiy/MVP_Example
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION