JavaRush /Blog Java /Random-MS /MVP dalam Android untuk si kecil

MVP dalam Android untuk si kecil

Diterbitkan dalam kumpulan
Apabila saya memulakan perjalanan saya sebagai pembangun Android, perkataan "Seni Bina Aplikasi Mudah Alih" menyebabkan saya sangat bingung, Google dan artikel tentang Habré mendorong saya ke dalam kemurungan yang lebih teruk - Saya melihat buku itu dan tidak melihat apa-apa. Saya fikir jika anda membaca artikel ini, anda telah mengkaji gambar ini lebih daripada sekali dan cuba memahami apa yang berlaku: MVP dalam Android untuk si kecil - 1Masalah memahami pendekatan seni bina dalam pembangunan mudah alih, pada pendapat saya, terletak pada keabstrakan seni bina itu sendiri. Setiap pembangun mempunyai visi sendiri tentang cara melaksanakan corak ini atau itu dengan betul. Contoh pelaksanaan MVP yang lebih baik didapati dalam sektor Internet berbahasa Inggeris, yang tidak menghairankan. Mari kita lihat secara ringkas apa itu dan teruskan kepada contoh. Model - tahap data. Saya tidak suka menggunakan istilah "logik perniagaan", jadi dalam aplikasi saya, saya memanggilnya Repositori dan ia berkomunikasi dengan pangkalan data dan rangkaian. Lihat — tahap paparan. Ia akan menjadi Activity , Fragment atau Custom View jika anda tidak suka menari dengan rebana dan berinteraksi dengan kitaran hayat. Izinkan saya mengingatkan anda bahawa pada mulanya semua aplikasi Android adalah subordinat kepada struktur MVC , di mana Pengawal ialah Aktiviti atau Fragmen . Penyampai ialah lapisan antara Paparan dan Model. View menghantar peristiwa yang berlaku kepadanya, penyampai memprosesnya, jika perlu, mengakses Model dan mengembalikan data ke View untuk rendering. Berhubung dengan Android dan contoh khusus, saya akan menyerlahkan bahagian penting - Kontrak. Ini ialah antara muka yang menerangkan semua interaksi antara komponen di atas. Untuk meringkaskan bahagian teori:
  • Lihat tahu tentang Penyampai;
  • Penyampai tahu tentang Lihat dan Model (Repositori);
  • Model dengan sendirinya;
  • Kontrak mengawal interaksi antara mereka.
Sebenarnya, contoh itu sendiri, untuk kesederhanaan percubaan, dengan mengklik pada butang, kami akan memuatkan baris dari pangkalan data dan memaparkannya dalam TextView . Sebagai contoh, pangkalan data mengandungi senarai restoran terbaik di bandar. Mari kita mulakan dengan kontrak: Mari buat antara muka MainContract:
public interface MainContract {
    interface View {
        void showText();
    }

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

    interface Repository {
        String loadMessage();
    }
}
Buat masa ini, kami hanya menyerlahkan 3 komponen aplikasi masa depan kami dan perkara yang akan mereka lakukan. Seterusnya kami akan menerangkan Repositori:
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 "Сосисочная у Лёхи»;
    }
}
Semuanya jelas dengannya, hanya memuatkan dan memunggah data. Seterusnya ialah Penyampai:
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()");
    }
}
Adakah anda ingat saya menulis tentang menari dengan rebana dan kitaran hidup? Penyampai hidup selagi Viewnya hidup, apabila membangunkan senario pengguna yang kompleks, saya menasihati anda untuk menduplikasi semua panggilan balik Lihat dalam Penyampai dan memanggilnya pada masa yang sesuai, menduplikasi kitaran hayat Aktiviti/Fragmen, untuk memahami tepat pada masanya perkara yang diperlukan perlu dilakukan dengan data yang sedang tergantung dalam "interlayer". Dan akhirnya, Lihat:
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()");
    }
}
Apa yang sedang berlaku?
  • Aktiviti, juga dikenali sebagai View, onCreate()mencipta contoh Penyampai dalam kaedah dan menyerahkan dirinya kepada pembinanya.
  • Apabila Penyampai dicipta, ia secara eksplisit menerima Paparan dan mencipta contoh Repositori (dengan cara itu, ia boleh dijadikan Singleton)
  • Apabila butang ditekan, View mengetuk penyampai dan berkata: "Butang itu ditekan."
  • Penyampai beralih ke Repositori: "Muat turun omong kosong ini untuk saya."
  • Repositori memuatkan dan menghantar "barangan" kepada Penyampai.
  • Penyampai beralih kepada Lihat: "Inilah data untuk anda, lukiskannya"
Itu sahaja, kawan-kawan. PS Adalah penting untuk menggambarkan dengan jelas tanggungjawab antara komponen. Sebagai contoh, dalam salah satu projek latihan saya, apabila mengklik butang, adalah perlu untuk menukar data dalam pangkalan data. Model itu diterangkan oleh kelas POJO, saya menyampaikan maklumat tentang lokasi pandangan, yang bertanggungjawab untuk maklumat mengenai objek pada skrin, Penyampai mencari objek ini dalam senarai dan menghantarnya untuk ditulis ke Repositori. Adakah semuanya nampak logik? Tetapi mentor saya menegaskan perkara berikut: Repositori HANYA perlu menulis dan membaca, ia tidak sepatutnya mengeluarkan maklumat yang diperlukan daripada POJO dan memutuskan apa yang perlu ditulis. Penyampai mesti memberikannya hanya maklumat untuk dirakam dan tidak lebih. Tiada rangka kerja yang ketat untuk melaksanakan seni bina: percubaan, cuba, cari apa yang sesuai untuk anda secara peribadi. Dan jangan lupa tunjukkan rakan senior anda pada semakan kod =) Contoh tersedia di GitHub: https://github.com/admitrevskiy/MVP_Example
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION