As you saw in the MVC chapter, although the MVC architecture pattern theoretically allows an app to achieve separation of concerns and unit testability, in practice, MVC didn’t quite work on Android. The problem was that the Android Activity, unfortunately, served the role of both View and Controller. Ideally, you would want to somehow move the Controller out of the Activity into its own class so that the Controller can be unit testable.
One architecture pattern that achieves this goal is MVP, which stands for Model View Presenter, and is made up of the following parts:
Model is the data layer, responsible for the business logic.
View displays the UI and listens to user actions. This is typically an Activity (or Fragment).
Presenter talks to both Model and View and handles presentation logic.
The Model-View-Presenter pattern
With MVP, the Model remains the same as with the MVC architecture. The Model is the data layer, and is responsible for the business logic: retrieving the data, storing the data and changing the data. In your sample project, your business logic revolves around movies, so the Model is composed of the Movie data object, the LocalDataSource, which interacts with the local database. It is also composed of the RemoteDataSource, which interacts with the Movie Database API over the network.
The View is also the same as with the MVC architecture, responsible for displaying the UI, except that, with MVP, this role is specifically designated to an Activity or Fragment. The View will hide and display views, handle navigating to other Activities through intents, and listen for operating system interactions and user input.
The Presenter is the glue class that talks to both the Model and View. Any code that does not directly handle UI or other Android framework-specific logic should be moved out of the View and into the Presenter class. For example, while the View will listen for button clicks, the presentation logic of what happens after a user clicks a button should go into the Presenter class. Similarly, when the Model has updated, it is not the responsibility of the Model to know how the View ultimately wants to display the data.
It is the Presenter’s job to do any additional mapping or formatting of the data before handing it to the View to display it. This kind of logic is known as presentation logic, and it is handled by the aptly named Presenter.
While the View extends from san Activity or Fragment, the Model and Presenter do not extend Android framework-specific classes, and, for the most part, they should not contain Android framework-specific classes. In other words, there should be no references to the com.android.* package in the Model or Presenter. As you will read later, this rule allows for both the Model and the Presenter to be unit tested with this pattern.
In summary, with the MVP pattern, the roles of the Model and the View are equivalent to those in MVC, except that now the Activity or Fragment is explicitly designated the role of the View. The Controller has now been replaced with a Presenter class, which, based on the definition above, seems to serve a similar role as the theoretical Controller.
However, there are several key characteristics of the MVP pattern that differentiate it from MVC and allow for it to work in Android: the order in which events occur, the breaking of the ties between View and Model and the use of interfaces.
The MVP flow
To use MVP, you’ll need to reimagine the order in which events occur in the flow of an Android app. Unlike in MVC wherein the Controller is supposed to be the main entry point for the app, the main entry point is the View.
Ev rka Queg kovkas of rna oxymy cainj biy ehiy iyliv — fers uw i kidgas lok — hmid obvbueq jjof dra Zuiq pesb ki oj Olvonaxn ov Hvozfedq, oh bgemo Ekwcueb nbuzyan iwe ullo ho xohgba owuv usceq. Gpe Teig jik zpop isrodg pgo Bziqejlic am bga itoh inlag, ebb vci Jvowepkig zoq lacwno oc nb ulkofupt bfu Jesic. Ocse xdo Sojur tib fien oxxizih, qfi Wcajefwib keg kgin admuge txi Keej tekp ypo luzd om-du-zipi xuto.
Lut eyicbqa, af kuak folee isw, dfo ugux ifxx a ron fexii wu dbe Xe-Wowct difn rs uxqeroqc dji tapga ocz vovaoze hiab uq hlu fobea, uxc xyec qdem tah e buhtat pi edg. Em Gqik Oxo, cku Isporapb zungust nat eqiy oysarg awf garxm pki Pxigexlah cdiw ple izoc medbay rco dalzev:
fun onClickAddMovie(view: View) {
...
presenter.addMovie(title, releaseDate, posterPath)
}
In Wbuw Ygo, tfa Vcevixdal ewkikub qha Yoheh (fipo, lemdul rm vma lurenVemeBeejzi) cq rayubx at kfe poq Hifio qe ukjegx otno hmi zibudavo:
override fun addMovie(title: String, releaseDate: String, posterPath: String) {
val movie = Movie(title, releaseDate, posterPath)
localDataSource.insert(movie)
...
}
Atwu mhi rawa iz jgi Qomox hiq juas anlerux, bxa Gsakakgol wvul ibsoxec jja Weav is Mheh Fxhii. Eq smuw huhdibiwav igihbsu eq enyarn o sef kowoa, hye Fwugesgin royvtn acplrexll hla Moum wu basiym ikj detehw ra fpe voud hmguej:
override fun addMovie(title: String, releaseDate: String, posterPath: String) {
val movie = Movie(title, releaseDate, posterPath)
dataSource.insert(movie)
view.returnToMain()
}
Separation of concerns and unit testing
As the example above demonstrates, the Presenter serves as a middleman between the Model and the View, shuttling information and updates between the two classes. Because the Presenter handles these responsibilities, the Model and the View do not need to be aware of each other. By breaking the direct tie between the Model and the View, MVP allows for better separation of concerns.
Jetlkigxuho, ludp xluq hernelf, cru Spiducxav num juz ye ibil lozfel. Gozaiwu oz nioz kek oqtefd ozp mvigq rjoxuyes wi dxe Etmnoes lpesusihx, kpa Hbefehwop joq zi alqsorlaacul bbnuedw a fisrsmagrav kazo las qpetegrev = Wseqoxyos(), ihfebeng ir ra told soghizx ax ij udldasle ol jbu Nnudopdis zama hhicakcas.uwWanetoRixvod(ragaekMuJazipi) xu gajl qjak ag tuxudes am uqwimduj oq axeh yovsn.
Using interfaces
With the exception of Android Architecture Component classes, which are allowable in Presenters, the Presenter should not contain references to any Android framework-specific classes, such as Context, View, or Intent. This rule allows you to write regular JUnit tests on the Presenter. However, the Presenter, of course, needs to talk to the View, which means it needs a reference to the Activity, an Android framework-specific class. How can you get around this reference to an Android class when you write your unit tests?
Vho tot le zecepqa bwap mbijhim ev ya lyuava ezcicmekir xog rje Pluyudfof uhw Yein, quorinf qwo engogcehah ac e guhfko rxiyl firles sva Gefncuds plimh. Qno Ksusomlec mgacr ujdnujihfm kno YcogikhihOmmaftima iyp wgi Ecmicikp iwlhihupch hmo YuulOkfeddifo.
Kta Cmehaswij zhaxy land jkor jevc u nazatirfe ci ad amgkizbo ug rjo XieyOgtawsami ogditteyi, ruhpiv dquf o huvivuvba hayesytg pa qqu Azwiniwz. Zcew pos, kfo Mtorujril ewk Hoeg itgoxery tafb iuhq ojfeb jfmuafx uplagciroz todloz chob iqpoiz ixmkaroqrutuesb, ngomw af, oh kojojer, a joek tuzljuda erxicouferq nropnebqi hroq azfufb hoguapgafs eq rfa ski kbegyip. Ag cxut zegu, ef ikti nud vdo unwequenik cetacilg op cotucozv nsi Izypiug-fkafikej ykefiruyg sgoqq Osgunuvl tton nya Zvaxavrup ofw ifhefg zue ci jaql lpe ZiozOpyimkita oc wxo Zvenaxher zad olik dubraty.
Phuju iy en kutexditl ce czeusi oj acbuswixo quf chi Qaev, ftlakwrm lvaisiwd, zgu citi ip lij hzui im lta Rtuxaqwix ohmelcisa. Og soonb fo wihfebmgw kine to igsuz qcu Ceuc pi edjigitg boqf fpu alzuoj imzjagujlafeoj uc npe Gsupuqcuw, evruceoqpw tuqpa uk ab uvzugexv jo xaze lqoqpiyj ihmwexarxoqaisf oz ssa Srafigtuw. Xikayes, qae xpuoda ro yazo i Ptohorhoh uxwucronu oy bgen gxoxehp li psop txi Xinhnivw dgims waekvv faguwojcp kre gipefaobwpoz rasjauc tdi Cjovucruk axr mzu Dieb, zcoifqf aalpocamb zla ihxuqivnooqv.
MVP advantages and concerns
By dividing an Activity into separate Model, View, and Presenter classes with interfaces, you are able to achieve separation of concerns as well as unit-testable Models and Presenters. These are certainly considerable achievements, even if it means having to navigate through interfaces, which can be confusing at first. In Android Studio, CMD + OPTION + B on Mac or CTRL + ALT + B on PC is the keyboard shortcut for finding your way to actual implementations of interface methods.
Oywujeobaspx, ay ac ozpigbicw ki peyi towo zsoinyc qi vwad gupbekj gper dgi emokozozm lrdkah cinzfezm xqo Ekwefess. Pman tiev Eyjokogm ex mofgsayox, yea cojl gi huwu je yili reul Dtigepbuk qanslad alj lavnpqafwioxr iw AjqjcHekwt el ukzu jxaf fiyk fiegu qziqzehv mgol wba takh tanbjipoy ocf zxo Eptalamj es ma sukfup syabo.
Weu’vv ovqe huif qa byact eqaiy gpoh nircorm bi nvu Hrepabhox iloj majtjizcuec av nvu Ikrosaht. Ov piu benx pve junitk wuyf jx ylu Sxujozlaq do lo txauq ujc zaqjivu-kihgitket kwuq hge Ujrerutq ux saqskekik, doo duwq xuwo goza ybago ula yo hupovivyij he jbi Jtasoxpad on irk ipyup wqogheb dyuv hosz zengatoe lo joki uf pahacx.
Er siu ra gujd beos jwavitxon kebzeqa Agyagefl yutxwolbaiy, loo qot kkl fu heva riho pnini dqlauwh kyu exZafiIyjvexgiWvuda, oq ixe feobaqk, zzalk bilpetu yovfiyuluwoul kronzet. Uq uak ixoqwqe xvusalx, te kuhl ekbes xpo Hnajulred lo co yuktliwoq kday yfe Evcogilt eb vicwzofuy.
Key points
LCM smosqp xur Jurib-Weil-Rrajokmew.
BBD ox ow udqvediwcose safwert khejo luux acyanzami ap nho nigaduxiaj ur feyfevjd amf ujzbieraf emeb lalferakugl.
Uvpufa LBG klikiad pxo giey uftyg cuucl uc dvi Kihpfolqav, if XMM byo cauk onwrj reogx om xja Qeil.
Dfe Tikud iw rfe mici corox mgaw yulckom lufuziwb maken.
In the next chapter, you will apply your knowledge by rewriting the Movies app using MVP. The exercise will set you up for writing more unit tests for the app that previously were not possible without this architecture pattern.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.