2016. április 29.

Android Architektúrák – MVP

10 perc olvasási idő

Android Architektúrák – MVP

Az Android platformon nincs semmiféle irányelv előírva, mit is illene tervezési mintaként használni. Így az utóbbi időben különféle megoldások bukkannak fel, mint például a Flux, MVVM, MVP. Ezek közül talán a legnépszerűbb az MVP.

Mi az MVP?

Egy jól strukturált kódban arra kell törekedni, hogy különböző, elhatárolt rétegekre osszuk fel azt. Ilyen réteg lehet a felület, adatbázis, vagy a hálózati kommunikáció kezelője.
Az MVP az MV* csoporthoz tartozó UI tervezési minták egyik variánsa. Ezek segítenek az interfész kódját elválasztani a logikától, így elősegítik a szerepkörök szétválasztását.

Model

Az adat, amit meg fog jeleníteni a felület.

View

A felhasználói interface, ami megjeleníti az adatot (model), és továbbítja az eseményeket a presenternek. Általában egy Activity osztály tölti be ezt a szerepet.

Presenter

A közvetítő szerepét játssza a model és a felület kötött. Ez dönti el, mi történjen, amikor a felhasználó kapcsolatot teremt a felülettel.

Model View Presenter diagram

Miért kell ez neked?

Androidon a probléma abból adódik, hogy az olyan osztályok, mint az Activity, szorosan kötődnek mind a UI-hoz, mind pedig az adatok betöltéséhez. Ez azt okozza, hogy keveredik a felület kódja, az egyébként máshova tartozó kóddal, ugyanazon osztályban.
Egy nagyobb feladat is kisebb részekre bontva, könnyebben megoldható. Ezt alkalmazva, amennyiben szétválasztod a kódokat különböző rétegekre, máris egyszerűbb lesz:

  • Tesztelhetőbb, mert minden osztálynak a többitől elhatárolt feladata van.
  • Könnyebb karbantartani, mert az osztályokban egy kódrész módosítása, jobban látható befolyással van más egységekre. A jobb tesztelhetőség, pedig lehetőséget ad a gyorsabb javításra.

Hogyan kell használni?

Egyszerűen tudod saját magad implementálni. A view osztályoknak egy interfészt kell implementálniuk. Ezen keresztül fog a presenter majd kommunikálni velük. A presenter osztályt is a viewban érdemes először feltölteni.


public class ExampleViewImpl implements IExampleView {

    private IExamplePresenter presenter;
   
    private void initPresenter(){
        presenter = new ExamplePresenterImpl(this);
    }

}

A viewnak butának kell lennie, és csak a megjelenítéssel foglalkoznia. Minden eseményt, ami történik, továbbít a presenternek hogy az cselekedni tudjon. Nem szabad elfelejteni, hogy a view-t a felhasználó irányítja, nem pedig a presenter!

A presenter osztályodnak ugyanígy egy interfészt kell implementálnia. Ezen keresztül fog a view kommunikálni vele.


public class ExamplePresenterImpl implements IExamplePresenter {

    private final IExampleView view;
   
    public ExamplePresenterImpl(IExampleView view){
        this.view = view;
    }

}

A presenternek nem szabad tudni semmilyen Androidos elemről, mert nem feladata ezekkel dolgozni. Presentere nem csak Activitynek és Fragmentnek lehet, hanem olyan felületi elemeknek is, mint egy TextView. Ennek ellenére egy presenter kezelhet több view-t is. Ha egy regisztráció több képernyőre fel van osztva, akkor elég lehet egy presenter hozzájuk.

Az implementált interfészek leginkább tesztesetek írásánál jönnek jól. Például létrehozhatsz egy saját view-t a presenterednek, hogy minden hívást, minden paraméterrel tesztelhess.


IExampleView mockView = new MockExampleView();
IExamplePresenter testPresenter = new ExamplePresenterImpl(mockView);

Egyik nagy problémája az MVP-nek Androidon, a presenter megőrzése konfiguráció váltás esetén. Például amikor fekvő és álló felület között váltasz, akkor a jelenlegi Activity helyett egy új jön létre. Ekkor ugyanazt a presentert kellene visszacsatolni, megőrizve például a másik szálon indított folyamatokat.

Erre több megoldás is van. Pár példa:

  • Singleton presenter
  • Kitalálni az onSaveInstanceState(Bundle) és az onDestroy() metódusokból, hogy mikor lesz konfigváltás
  • setRetainInstance(true) használata Fragmentek esetén
  • Loader osztály használata
  • Presenter osztályok cache-elése

Mindegyiknek van hátránya. Singleton esetén a presentered nem újra felhasználható, és static változó esetén az app élete végéig a memóriában marad. setRetainInstance(true) használata esetén a Fragmentre külön megkötések lesznek érvényesek.

Könyvtárak

Léteznek könyvtárak, amik segítenek implementálni az MVP-t. Ezek már megoldották a konfigurációváltás problémáját.

A Nucleus egy egyszerű lib. Egy rövid dokumentáció van, és példa kód. Itt a presenternek saját életciklusa van.

A Mosby egy jobban dokumentált könyvtár. A presenter megőrzését pedig egy ViewState funkcióval végzi el.

Vaszil Ádám

Már sok-sok éve szeretne programozó lenni, de mivel ennyi nyelvet nehéz megtanulni, ezért inkább csak a Javara koncentrál.

Vaszil Ádám

Hozzászólások