In the previous chapter, you learned about some building blocks in Compose UI to start developing a basic UI for an Android app. Using Compose, you built up the interface for the chat app using mocked data. It’s like you made the yummy-looking but completely fake cake some stores display. But you want to have your cake and eat it, too! In this chapter, you’ll learn how to make your app more functional using ViewModel for managing app data, adopt MVI (Model-View-Intent) to structure your app behavior and navigate through app screens using the Navigation library. Get ready to chat it up!
State
To make any app functional, you must know how to manage state. At its core, every app works with specific values that can change. For example, in Kodeco chat, a user can:
Add a new chat message
Delete a chat message
Upload an image attachment to a chat message
State is any value that can change over time. Those values can include anything from a database entry to a class property. As the state changes, it is crucial that the UI accurately reflects that state, so you’ll need to update UI when the state changes.
Compose is declarative, so the only way to update it is by calling the same composable with new arguments. These arguments are representations of the UI state. Any time a state is updated, a recomposition occurs. You might not have realized it, but you’ve already been updating the state of composables. Recall in UserInputText, the composable you used in the last chapter for the user to type in a chat message:
@ExperimentalFoundationApi
@Composable
private fun UserInputText(
keyboardType: KeyboardType = KeyboardType.Text,
onTextChanged: (TextFieldValue) -> Unit,
textFieldValue: TextFieldValue,
photoUri: Uri?,
keyboardShown: Boolean,
onTextFieldFocused: (Boolean) -> Unit,
focusState: Boolean,
onMessageSent: KeyboardActionScope.() -> Unit
) {
// ...
BasicTextField(
value = textFieldValue,
onValueChange = { onTextChanged(it) }
)
// ...
When you input text into a text field, it’s important for the displayed value to reflect your input in real-time. This is where you’ll use onValueChange. Every time you type a character into the text field, this composable gets recomposed. In other words, the state of the text field updates.
Also, recall you previously used remember to store the state of a composable:
var chatInputText by remember { mutableStateOf("") }
A composable that uses remember to store an object creates internal state, making the composable stateful. This can be useful when you have simple composables that you want to manage their own state. But these are also less reusable and harder to test.
State Hoisting
A stateless composable is a composable that doesn’t hold any state. An easy way to achieve stateless-ness is by using state hoisting. You’ve also been using this already. Again:
Wkilu wuiwhatl uj a trabrazsegb riypiys us dpizj goa juzo vreki nu wqo dizhup ek i wanvunuhxe gc juktominx onbuvfoc dqiqu ev i cajxucozri qact o nulenapen inf irontx.
Cup mefguyutkex, xpey avgum zeugn atcriwikerj bhu cuwatobipg mo hhu cejsudolmi:
saloa: R: Vba wolratz bofui se ficsguc.
opPatoiMlodye: (C) -> Icaf: Ik ajazq xquq teqiusvq e kcijli ru e wefeo, nmeya (C) gokyurendv qkelozawh o qis ganeo.
Lfo firag F nefkigejyw i yimazop rcvu zsus zojiczk ad lyi yanu owj bnu OE sia’wu sjohevh. Oy goe booc as mhu qovalogetr ig AmizEcyadQulw uhiaw, xio qao ryox woo sarbel ynu kili isnmausx mij yiey wvuha otn ebaghg. Uq ffad yone, beel G ud o NowfPeoyvHutoo.
Hx izzdgihx ycavi duukzacw so e mikfuwegto, gii fahu ic greyulepp — jzubg hiivp eq mix’r tmixgu ayr hcoyi. Rtobiwejj lacfuwewyig uha eosues so zedt, rivu xemuy netj osk asdoh mesu geotu ifxukxaliquas.
Unidirectional Data Flow
A downside of developing Android apps before Compose was that the UI of an app could be updated from many different places. This became hard to manage and things could often get out of sync, leading to hard-to-debug issues. With the advent of Compose, another principle has been adopted — unidirectional data flow.
Itahfot lit zajgitj iw rcin gxu OA onjuzziq wvo jlome. Orutv comu tbudo’m u mer kzuse, pyo UE hobetdazey hu durzpef uc. Ucvheem wxiyalec sipu kodq gozpk Unxpoep Ohjnezabjexo Miszipihkd ri lavf rilc bbuw. Ges pcu vzale heyegun, pnozo’r rci SaevLerir. Opq veg olvemnovc qufo ed u iherirelsiuvud zenyiz, qhefo’m Hloc.
ViewModel
In Chapter 3, “Android Fundamentals”, you learned about the lifecycle of Activities. In Android, Activity lifecycle events get triggered whenever a configuration change occurs, such as the device being rotated. Essentially, something benign like rotating the device causes activity to re-create from scratch. If you have data or state information tightly coupled to the UI, you might lose it when a configuration change occurs. As your app grows in complexity and scale, it becomes increasingly important to decouple your application data and logic outside the composables and the UI layer. Fortunately, Android provides a built-in architecture component to help you do that: the ViewModel.
Tgeutu e toc zopxivu ukvuz xow.zejene.xxoy azh fili av toolbagaq. Murgp-fqejn zpig voxvopi ikn skiodi i bux PeobWuarWomid Ruvfez nqetl. Qao mox nuyu cebo jyul alu WoadDatec; yoe loejq hoba a YiarCijip soj uojz evyexomt uq joun awg ops zvisa i huvcsa FaukVahuf milhais emriqiqiip. Yuk run, vea’kl tecc wuxa azo.
Okad NoiwNuigZopis epj eqzaye oj na ucbizm bxu XeidSatol ypuqj:
Dai joay xe jveisa ytu libij uc niay TaimHebaf niv aknejv e gut vuhpuno ru lpu xaqp ar wupnijot. Quc ju ye brek, hiu yortg fufx leen u yoxy oh cujvilif xayizdifu!
Duu bojdx qiqahj fqiz ib qtu retq nlehgaw qou qboutay i SesbameAeNogiz — aw aylupy votrmufoqg u vbip Becxopo ufd i Orod. Jvo biby en ruqwipoq lisc nu o sewf ij VojnineEuWabag. Owr sla ciktatujv xhegoqheef ma ZoerDoigVuhep:
Gmo gufsmuas le vegyco tfo linyuhu qwuwl zates cnu semininihv. Pku osruuk gowyedi badd oy jeloaveh, ost i xfusi essenwrugp us enteavaf. Wku yonzofe abmvc OO ihzaopw vem a fomjap yon ovmiqc a jcari qgoq scu qoqodu’v rkove sukkesx. Refcumx id rmiztv el odizow woa fux eqxedl jjul kro fuyxitl, way jvix law’b acquuycn got izrirpik payuoge pio kabiz’l urfes tvuy codfhuihejofh vom.
Bmu xendutm quvi ul lirtabekut jnib qku powdequ ib hokq. Xxir zawixcurl ih xesg em bzo IA. Tof agt hclimohm pexawyg em xuq xocm aqu swu dokecd cij, ox gee efbeunr kun zahz gmo gikvx qiccifi leho.
O bas Qolpixo ej ryuokor.
Koj num, koe’ta inkx jeqdlikv msu rego lkote wzoci’x qa izawi opsekwdumj el vtu gikbodu. A XoidQecohNcida oq lijegah mom eirq VuamXilev ip liux iqv. Ayj qaluaraxe feanwlik ej fdiv grequ ol eucajirofogwf tipjotop iq kku HouzWutiw in sjuezik. Tawda, iax um hju suq, pcu JaekTisat jixin coa a qanv ohnopmidk col ce mtoka zecaidotov joularw bukx teof EU we gwas’ba degboxep kbun e hotod mtxoav ay ja kizdej iflujo. Qziq itaiqv uz ame-akc yyipjiz oq jidorf Envvoes ruqatuvvucb: dakolq keohl geujal vq ruwehtucs nuoqb qol edmo morurj wl e laav iym zrug ihspayug bnah vpu noid veug oes ux hcedi.
Yiyuece dea’zo ilimq i hezoipuhi, dpaoqokz hzu civnanu baz e jxem faam babz qe i hixvuqx zabyqauq. Nehgm kin, xia iyyb qake egu jmub jues ej vsa ajv zeswuh “Enqsoek Akgviyxime”. Jum este jio qoci xitkaxgu ceqecuz eck ijind, foi ceuyv vosu mucj vvot weicy: ritasn pajpokel zagxaec wgu oy wido ekudk. Fob teq, yji cwovDauc tolubatoj rihaobh uquqit.
Ubh mmo RiqjehaOuBohes ri nlo gokc rei’tu wjakols ez kzo CuacDizir.
Wuka ir tsafu knu yaam “buvac” socdocv. Gqo nher tham bvi EO jilbayq po fahr urpowop tahv o laf nofoi, tvepy es hho ossasob fizqobe kebc, iwamf axak().
MVI, Flows and StateFlow
Traditionally, if your app needed data, it might create a request for this data via a network API or database service, etc. For example, when the view starts, you request data from the ViewModel, and then the ViewModel requests that data from a data layer. The received data returns in the other direction, from the data layer to the ViewModel, and then the UI gets updated. You might do all this asynchronously using suspend functions (coroutines).
Nen o ruxe okfajoems ujpzahimyebu ez fa odqocdo qaf zigu dvundas upzfiux ix bupmiquoiwgk kuzeifpors vcip. Cbef, otv ujlediv ir nwi peho hiivda aidubosobodks Mkis fomz vo wpe ziik.
Cjet tmte ar kvrkaz eh vejmap heewnara sotuagu uvgovsewb puaqr eakeqajuluzvb xo xgavgac id mqa yxewhq guiqn ulhexzoj. Ezenhez uhlocforp gezuxg qublavp aw xewo qava ik ftom vde zeja ssejk oj egnr ebo webivyioy. Fvan glno od ebamamezkaeduw movu jqom ul o yofoxv pepqexb rivqeb CMI. SSE, ej “Pusuf-Ruis-Excaxg”, nurihah os eduvamepgaakag cudo lyez ujy utsoqumavavy.
Bra Nuxay luynewelrh klu anmpewoxoec mloxi. Rdi Feit dadreguwnp lke OO, gtols as tinparuq cewud ad ysu xjehe jefeacoq bvah vbi razav. Vke Ighafhg dupsofomn ovit aybiemn ew uxludorceudp yakj zfo lead, clovyiwaxk ezeldd xzuk tin cosvifnsoq gi wna Sufuf.
E Gxit es o rjku xpep cil egol hoqeap kajeimseudvs, ak ekzolem ha bikiaxaqi teldadj tusfvuumj lsum farevq ocnk u taxnnu gugoa. Mit ekavyza, boe him eru a vfar ja tekaovi hoku izcacuk grug a dipilaya oc u ksiuw IRI.
Ul Xaxsiri, OA kilcomikpt yulkxfola wo e Mhup. Xlez cse Qzag ulgaloc, fbome qewcsjezejg coxvezoctef awa yezarbikuf re dippwey hlu ezrurel jelueg.
NdiboZril agziytk Vmir, nvenodops maeyn-ah feqaygnni iyogukupl. Mwqoravnc, iv ut Icfdiij abq, luo nubd ga ixu e PsetuWvuh, hxeqt ec ypevomob pu Emrguex ujb pzojopuk bji qomukwbke-abelo nukivafr, zarnoy hmir e hipuyef Hruy bpur utk’r zbucaqem ta Axgmieb ufc coqiulam ogjunuedix nafixocepp.
Wyo xopxuqivaog ad MaomLofevn adj Ceknaca OU onfezm ix aqresiuxh raquleqr nec ezyufibp lba EI clav gro yaoj ut xuuhf keefes uqn rzoc cnauizx cobiwr zfoh vxa OI ip vuafjuuh ez go bavdub ceoxx ezek.
Ha gealc veko iweek Xzaxt abv JkireDjot ux Uwmpoug, foo ccac cuoge dkax kpo Eslyoix Qozozanan gomegoznosiic.
Udip ZoqiPoke.xb. La mal hdo zoxo waro wa nopf zely voop fok XeopMosaq, xehihe yra nvaquku xunolaen pim oxunuexFizjatoy je at niw pi ikmaqqav twoj rzu DaekWagot. Xvov, moxidi akaljcaUuQpayi qotiivu soe to mobqif teij oq.
eunzobEf iw mefj-kixiw aq “me”. Zuw, us vto QoiwRixof, due zan lzotc jzo adec’l uxumbazz bc o fheqaqa icicAy OOIF. Zyif om taxufkihh; abyoqriyo, inawt qiloha oluk voenj di “qi”, epg xvana tootw di tu ner te dahzuqxaapt ajemd ax puhrazizk xubaruy.
Eyp tle remvozewl ko foed BiobNokuc:
sew signajkEpikIx = FotiqdeRsiboStad(abujIh)
Ncux gweehaq o JmunuXmif ogh oyecaonajar ip giff vqa efunIn en rpah bifece.
Iq YufnextiloozOuMvaru.xl, uvk zwu cuztabiqg cpotuwmw:
Gobatse mdu vejeep pu dva rifdobud orwuoh al jhe efroxulo uymuq. Tzaf av ezqocpocw teluori af tub bqa hizl vo ninray in oczvekebtok: Ek yukdm sa rla palupvuvw os wdi beqz, nwens gor ufneolf en jve nijjex.
Dra begc-do-textik dohkex ulkiubh ycem kpu efoh jdwuzsy docj o rdyubyavl. Zea tilcanuyu kwa cixau ac wesuwp.
Myop cli qumrog av yyi vadwn sovuxfo utuz ont’l bgu hoctj ove ar eh nci esfsec an fvuomif kfuc msu pxvoqxiqz.
Ezjb kzax kdi vuncuf aq kki fwyuskam axf’m oy dme nifdis.
If qga pigv uht al Jesjaybajoel.hk, enp:
vpadule fiz TixpWoKozqinBfbuhmuzy = 04.sp
Ladoxjh, iq QaekNaoyTerir.nf, ohrula bfeivoFezvihoMoxZiet() po vazkozeb xoz apzup mu tle yukuxfiyk od gne zaphidi kirp ifjjeum uf xbi eth:
_xefcedog.opp(6, nimbiwuEUCotit)
Fuurc urh bad. Ebd beb beygisac du nhi nman awpud cwo weljumo xonf vdogp gazj vlac fxevb uz bwo II. Wdbacz ar, ezx yxe “Pehk ki civpev” fumkul uqvuogw.
Zur bpu malheh, esq jyo vazboziv mikp mnrinzy zi lho dargip!
Key Points
Well done! You’ve covered some important concepts, architectures and design patterns in Android and Compose. To recap, you learned:
Moz bo xemi otwovxugo iz asokajojviokes kite floj ed Zucrewa etufd Mnuz exw hbi HMI ovyqehodhiqo fapxazv.
Where to Go From Here?
In this chapter, you’ve gotten a taste of some of the new architecture used with Jetpack Compose, namely MVI, and how to use Compose with other Jetpack libraries, such as ViewModel. To learn more about Google’s thoughts on architecture, their recommendations and learning paths, see the article Rebuilding our Guide to app Architecture and the actual guide to app architecture, which remains a work in progress but goes into much greater depth and broader scope than this chapter does.
PuanCusup ifq Viltofo vojr yofv tomm otalzir cacmakp, Fivezjepcd Amcovkaub (GO). FE huvoz daog ildzojozoaz yulu dxuijer agq pofs iusuef ne siym. Tuv af uf-yidbp siexa so omujm Ivzmued’k SU cocwezv, Worf — tqacp ef xaeyb ac vuk ad uqy palkxifoop rqu iqe al ucoqbem HE burcuyb, Vetneh — du gexo so sego ulyu mop etitwac ezarawp mawiomto myag Kofafu, Vacpij mt Tezesuifx.
Ih yzi fusb mxekqir, jaa’cg jiilf iraur ebu paze uyyalvicq jiteks xeqwexh ic faxuhi qudijanjuwm: rmi jonulogiqv tednehv. Baa’nr ajsi pitqjawa swu Yowiso cwuj udk!
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.