JavaRush /Java Blog /Random-TW /兒童的 Android MVP

兒童的 Android MVP

在 Random-TW 群組發布
當我開始擔任Android 開發者的旅程時,「行動應用架構」這個詞讓我深感困惑,Google 和Habré 上的文章讓我陷入了更大的沮喪——我看著書,什麼也沒看到。我想如果你正在閱讀這篇文章,你已經不只一次地研究過這張圖,並試圖理解正在發生的事情: Android 中適合小朋友的 MVP - 1在我看來,理解行動開發中的架構方法的問題在於架構本身的抽象性。每個開發人員對於如何正確實現這個或那個模式都有自己的願景。在互聯網的英語領域中或多或少都可以找到 MVP 實施的不錯例子,這並不奇怪。讓我們簡要地了解一下什麼是什麼,然後繼續看一個範例。 模型-資料等級。我不喜歡使用「業務邏輯」這個術語,所以在我的應用程式中我將其稱為儲存庫,它與資料庫和網路進行通訊。 視圖——顯示層級。如果你不喜歡手鼓跳舞以及與生命週期交互,那麼它將是ActivityFragmentCustom View 。讓我提醒您,最初所有 Android 應用程式都從屬於MVC結構,其中控制器ActivityFragmentPresenter是View和Model之間的一層。View 傳輸發生在它身上的事件,presenter 處理它們,如有必要,存取 Model 並將資料傳回 View 進行渲染。關於Android和一個具體的例子,我將重點放在重要的部分——合約。這是描述上述元件之間所有互動的介面。 總結理論部分:
  • View 知道 Presenter;
  • Presenter了解View和Model(Repository);
  • 自行建模;
  • 契約控制著它們之間的相互作用。
實際上,在範例本身中,為了實驗的簡單性,透過點擊按鈕,我們將從資料庫載入一行並將其顯示在 TextView。例如,資料庫包含該市最好的餐廳的清單。 讓我們從契約開始: 讓我們建立一個介面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()");
    }
}
這是怎麼回事?
  • Activity,也稱為 View,onCreate()在方法中建立 Presenter 實例並將其傳遞給其建構函式。
  • 當建立Presenter時,它明確接收一個View並建立一個Repository實例(順便說一下,可以將其做成Singleton)
  • 當按下按鈕時,視圖會敲擊演示者並說:“按鈕已按下。”
  • 演示者轉向存儲庫:“給我下載這個垃圾。”
  • 儲存庫載入“內容”並將其傳遞給演示者。
  • 演示者轉向視圖:“這是給你的數據,畫出來”
就是這樣,夥計們。PS 明確劃分組件之間的職責非常重要。例如,在我的一個培訓專案中,當您按一下按鈕時,需要更改資料庫中的資料。該模型由 POJO 類別描述,我傳遞了有關視圖位置的信息,該視圖負責有關螢幕上物件的信息,Presenter 在列表中查找該物件並將其發送到儲存庫。一切看起來合乎邏輯嗎?但我的導師指出了以下幾點:儲存庫應該只進行寫入和讀取,它不應該從 POJO 中提取必要的資訊並決定需要寫入什麼。演示者必須只向他提供錄音信息,僅此而已。實現架構沒有嚴格的框架:實驗、嘗試、尋找對你個人來說方便的東西。並且不要忘記向您的高級同志展示程式碼審查 =) 該範例可在 GitHub 上找到: https: //github.com/admitrevskiy/MVP_Example
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION