';

Model-View-Presenter (MVP) to wzorzec architektoniczny przeznaczony dla oprogramowania posiadającego interfejs użytkownika. Wzorzec ten zakłada, iż każde wywołanie interfejsu użytkownika przekazywane jest do obiektu Prezentera, który implementuje logikę biznesową. Główną zaletą wzorca MVP jest rozdzielenie (ang. decouple) logiki biznesowej od Widoku (tj. od Activity w przypadku Androida), gdyż ani Widok, ani Prezenter nie zależą bezpośrednio od swoich implementacji, a jedynie od swoich interfejsów.

Znalezione obrazy dla zapytania Model View presenter

W celu zwizualizowania wzorca, zaimplementujemy bardzo prostą aplikację dla platformy Android z wykorzystaniem Model-View-Presenter. Użyjemy do tego Android Studio, języka programowania Kotlin oraz systemu budowania Gradle.

Zacznijmy od części wspólnej wszystkich Prezenterów – interfejsu BasePresenter.

interface BasePresenter<in T> {
    fun attach(view: T)
}

Słowo kluczowe in w deklaracji parametru generycznego T, informuje kompilator o tym, że klasa BasePresenter skonsumuje zarówno klasę T, jak i wszystkie klasy jej pochodne. Mechanizm ten nazywamy kontrawariancją (ang. contravariance) (https://kotlinlang.org/docs/reference/generics.html#variance).

Naszym kolejnym krokiem jest zapisanie kontraktu pomiędzy Widokiem a Prezenterem. Kontrakt ten zdefiniuje interfejsy, których oczekiwać będą wzajemnie od siebie Widok i Prezenter.

interface MainActivityContract {
    interface View {
        fun update()
        fun showError()
    }
    interface Presenter : BasePresenter<View> {
        fun load()
    }
}

Powyższy kod definiuje następujące zależności:
– Prezenter posiada informacje, że na obiekcie widoku wywołać może funkcje update() oraz showError().
– Widok może wywołać funkcję load() na podanym mu prezenterze.

W tym artykule nie jesteśmy zainteresowani implementacją samego prezentera. Jedyną ważną informacją jest to, iż zawiera on logikę biznesową, której nie ma ani w Modelu, ani w Widoku.

Zajmijmy się zatem wykorzystaniem prezentera z perspektywy Widoku.

class MainActivity : AppCompatActivity(), MainActivityContract.View

Po pierwsze, MainActivity musi zaimplementować interfejs widoku zdefiniowany w kontrakcie pomiędzy nim, a prezenterem.

W celu pozyskania obiektu prezentera w MainActivity, powinniśmy wykorzystać jeden z popularnych frameworków Dependency Injection / Inversion of Control, tj. Dagger2 lub Koin. Mogłoby to wyglądać następująco:

    @Inject lateinit var presenter: MainActivityContract.Presenter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        injectDependencies()

        presenter.attach(this)
    }

Każdy obiekt prezentera dla MainActivity MUSI implementować interfejs zawarty w kontrakcie.

Gdy już obiekt zostanie poprawnie wstrzyknięty do MainActivity, możemy go wykorzystać w następujący sposób:

    override fun onStart() {
        super.onStart()

        presenter.load()
    }

Voila! Wiemy już, jak zaimplementować prostą aplikację z użyciem wzorca MVP.

Wykorzystanie MVP to dobry sposób na tworzenie aplikacji dla Androida. W łatwy sposób możemy rozdzielić logikę biznesową od interfejsu użytkownika, a utworzone komponenty są re-używalne. Niestety, MVP nie jest doskonałe. Dlaczego?

  • Tworzymy dwustronną zależność pomiędzy Widokiem i Prezenterem.
  • Prezenter gromadzi też zależności do wszystkich serwisów, z których korzysta.

MVP było rynkowym standardem, aż do momentu wdrożenia wzorca Model-View-ViewModel w bibliotekach Androida. Ale o tym opowiem przy okazji osobnego artykułu.

Recommend
Share
Tagged in
Leave a reply