JavaRush /Java-Blog /Random-DE /MVP in Android für die Kleinen

MVP in Android für die Kleinen

Veröffentlicht in der Gruppe Random-DE
Als ich meine Reise als Android-Entwickler begann, versetzten mich die Worte „Mobile Application Architecture“ in tiefe Verwirrung, Google und Artikel auf Habré trieben mich in eine noch größere Depression – ich schaue mir das Buch an und sehe nichts. Ich denke, wenn Sie diesen Artikel lesen, haben Sie dieses Bild bereits mehr als einmal studiert und versucht zu verstehen, was passiert: MVP in Android für die Kleinen – 1Das Problem, den architektonischen Ansatz in der mobilen Entwicklung zu verstehen, liegt meiner Meinung nach in der Abstraktheit der Architektur selbst. Jeder Entwickler hat seine eigene Vorstellung davon, wie er dieses oder jenes Muster richtig umsetzt. Mehr oder weniger gute Beispiele für die MVP-Implementierung wurden im englischsprachigen Bereich des Internets gefunden, was nicht überraschend ist. Schauen wir uns kurz an, was was ist, und gehen wir dann zu einem Beispiel über. Modell – Datenebene. Ich verwende den Begriff „Geschäftslogik“ nicht gern, deshalb nenne ich ihn in meinen Anwendungen Repository und er kommuniziert mit der Datenbank und dem Netzwerk. Ansicht – Anzeigeebene. Wählen Sie „Aktivität“ , „Fragment “ oder „Benutzerdefinierte Ansicht“ , wenn Sie nicht gerne mit einem Tamburin tanzen und mit dem Lebenszyklus interagieren. Ich möchte Sie daran erinnern, dass zunächst alle Android-Anwendungen der MVC- Struktur untergeordnet sind , wobei der Controller eine Aktivität oder ein Fragment ist . Presenter ist eine Ebene zwischen Ansicht und Modell. Die Ansicht überträgt die auftretenden Ereignisse an sie, der Präsentator verarbeitet sie bei Bedarf, greift auf das Modell zu und gibt Daten zum Rendern an die Ansicht zurück. In Bezug auf Android und ein konkretes Beispiel werde ich den wichtigen Teil hervorheben – den Vertrag. Dies ist die Schnittstelle, die alle Interaktionen zwischen den oben genannten Komponenten beschreibt. Um den theoretischen Teil zusammenzufassen:
  • View weiß über Presenter Bescheid;
  • Der Präsentator kennt sich mit Ansicht und Modell (Repository) aus.
  • Modell für sich;
  • Der Vertrag regelt die Interaktionen zwischen ihnen.
Im Beispiel selbst laden wir zur Vereinfachung des Experiments durch Klicken auf eine Schaltfläche eine Zeile aus der Datenbank und zeigen sie in einer TextView an . Die Datenbank enthält beispielsweise eine Liste der besten Restaurants der Stadt. Beginnen wir mit dem Vertrag: Erstellen wir eine Schnittstelle MainContract:
public interface MainContract {
    interface View {
        void showText();
    }

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

    interface Repository {
        String loadMessage();
    }
}
Im Moment heben wir lediglich die drei Komponenten unserer zukünftigen Anwendung und deren Wirkung hervor. Als nächstes beschreiben wir das Repository:
public class MainRepository implements MainContract.Repository {

    private static final String TAG = "MainRepository";
    @Override
    public String loadMessage() {
        Log.d(TAG, "loadMessage()");
        /** Здесь обращаемся к БД oder сети.
         * Я специально ничего не пишу, чтобы не загромождать пример
         * DBHelper'ами и прочими не относяшимеся к теме ein Objektами.
         * Поэтому я буду возвращать строку Сосисочная =)
         */
        return "Сосисочная у Лёхи»;
    }
}
Damit ist alles klar, nur das Laden und Entladen von Daten. Als nächstes kommt der Moderator:
public class MainPresenter implements MainContract.Presenter {
    private static final String TAG = "MainPresenter";

    //Компоненты MVP Anwendungen
    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()");
    }
}
Erinnern Sie sich, dass ich über das Tanzen mit einem Tamburin und den Lebenszyklus geschrieben habe? Der Presenter lebt so lange wie seine Ansicht. Wenn Sie komplexe Benutzerszenarien entwickeln, empfehle ich Ihnen, alle View-Rückrufe im Presenter zu duplizieren und sie zu den entsprechenden Zeitpunkten aufzurufen, um den Aktivitäts-/Fragment-Lebenszyklus zu duplizieren, um rechtzeitig zu verstehen, was benötigt wird Dies muss mit den Daten geschehen, die derzeit in der „Zwischenschicht“ hängen. Und schließlich Ansicht:
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()");
    }
}
Was ist los?
  • Aktivität, auch View genannt, onCreate()erstellt eine Presenter-Instanz in einer Methode und übergibt sich selbst an ihren Konstruktor.
  • Wenn ein Presenter erstellt wird, empfängt er explizit eine Ansicht und erstellt eine Repository-Instanz (übrigens kann er zu einem Singleton gemacht werden).
  • Wenn eine Taste gedrückt wird, klopft der View an den Präsentator und sagt: „Die Taste wurde gedrückt.“
  • Der Moderator wendet sich an Repository: „Laden Sie diesen Mist für mich herunter.“
  • Das Repository lädt die „Sachen“ und liefert sie an den Präsentator.
  • Der Moderator wendet sich an View: „Hier sind die Daten für Sie, zeichnen Sie sie.“
Das ist es, Leute. PS: Es ist wichtig, die Verantwortlichkeiten zwischen den Komponenten klar abzugrenzen. In einem meiner Schulungsprojekte war es beispielsweise beim Klicken auf eine Schaltfläche erforderlich, Daten in der Datenbank zu ändern. Das Modell wurde von einer POJO-Klasse beschrieben, ich habe Informationen über den Speicherort der Ansicht übergeben, die für Informationen über das Objekt auf dem Bildschirm verantwortlich ist, Presenter hat in der Liste nach diesem Objekt gesucht und es zum Schreiben an das Repository gesendet. Scheint alles logisch? Aber mein Mentor wies auf Folgendes hin: Das Repository sollte NUR schreiben und lesen, es sollte nicht die notwendigen Informationen aus dem POJO ziehen und entscheiden, was es schreiben muss. Der Moderator darf ihm nur die aufzuzeichnenden Informationen geben und nichts weiter. Es gibt keinen strengen Rahmen für die Implementierung von Architektur: Experimentieren Sie, probieren Sie aus und suchen Sie nach dem, was für Sie persönlich am bequemsten ist. Und vergessen Sie nicht, Ihren älteren Kameraden die Codeüberprüfung zu zeigen =) Das Beispiel ist auf GitHub verfügbar: https://github.com/admitrevskiy/MVP_Example
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION