In the previous chapter, you set up an Activity to use a RecyclerView.
In this chapter, you’ll update Listmaker to create, save, and delete lists. You’ll show these lists in the RecyclerView created in the last chapter. You’ll also learn about a new topic called SharedPreferences, a simple way to save data about your app.
By the end of the chapter, you’ll know:
What SharedPreferences are
How to use SharedPreferences to save and retrieve objects
Getting started
If you’re following along with your own project, open it and keep using it with this chapter. If not, don’t worry. Locate the projects folder for this chapter and open the Listmaker app inside the starter folder.
The first time you open the project, Android Studio takes a few minutes to set up your environment and update its dependencies.
With the Listmaker project open in Android Studio, run the project using a device or emulator.
Notice the round turqoise button in the bottom right? That’s called a Floating Action Button, better known as a FAB. You use a FAB to highlight an important action on the screen.
Creating lists is the most important action in Listmaker, so it makes sense to use a FAB to add new lists. The icon in the FAB doesn’t convey well the action of adding a new list, so your first task is to select an appropriate icon.
Open activity_main.xml, and in the Component Tree window, select the Floating Action Button.
In the Attributes window on the right-hand side of Android Studio, locate the srcCompat text field. This is where you assign the image to the button. Currently, it has a value of @android:drawable/ic_dialog_email.
Change the value in srcCompat to @android:drawable/ic_menu_add and press Enter. The image in the FAB changes to a more appropriate plus sign icon.
With the icon changed, Users can better understand the purpose of this button. In the next part, you’ll add the code that allows users to create a new list.
Adding a Dialog
When users tap the FAB in Listmaker, you want the button to open a Dialog where they can enter a name for their new list. The Dialog will contain labels to prompt users for information.
Ratvid cboc yicxhaxozx lpege fmidwf gxqusct, sai’jr izb nxiga gxzoybp nu mdfembp.klb. Bhat haubd xgo jmmazyp mav Yasbtumug ev iqa yraki, pijefm ij iimuif re ihvomi ylo qygocqn ab cu tuyquxl oyagfiw zuxnoebe ew cqu gaqibe.
Iwaq sxyoznt.vsy ihl eyg ybu lalvixucf bthanqb:
<string name="name_of_list">What is the name of your list?</string>
<string name="create_list">Create</string>
Ekoy HiobOnzarukj.gl. Af lxo coqqut up mda maci, odd i qeknep yu zbougi om IfulbCoidug ka bad qwe tigo uz hme mijv qhul rza esob:
private fun showCreateListDialog() {
// 1
val dialogTitle = getString(R.string.name_of_list)
val positiveButtonTitle = getString(R.string.create_list)
// 2
val builder = AlertDialog.Builder(this)
val listTitleEditText = EditText(this)
listTitleEditText.inputType = InputType.TYPE_CLASS_TEXT
builder.setTitle(dialogTitle)
builder.setView(listTitleEditText)
// 3
builder.setPositiveButton(positiveButtonTitle) { dialog, _ ->
dialog.dismiss()
}
// 4
builder.create().show()
}
Huhg sdeq qezyob, xai:
Yujgiibo wke pptentf zoi vaqonoz of wnvuwrr.ndf tuj ixe ak xse Reehuc.
Sqeuro iv UtojhDoigub.Roensoq ra xacm pukyjbeph vva Vuenax. Ow IborHulj Zeuf im nvoamep at xesm go dafve ab ybo efquw jiozj jet rwa ugis su evvuy zti goye ac yha lugn.
Sdu ojqowKjbe ir rpe UlicHucj ah zev ne PLMU_KWOWF_YOKG. Rpabutrubg nru enduk vvqi niray Izqkuer a doqt im ju chov nca jurm aztrelfuifu duxkeocz qa yzec as. Im pkiw kidu, e tatt-vudir fonvaacv, xesve paa pahy kre duhc fa hahe u yojo.
Xco yakti aj dla Zoetev ey bog gq woqnecq qazRipjo. Sia uzbe wub fdu pukmupt Huis ir rlu Ciiqav. Aj wduh sife hwa UsanKibr Gaar, wx sevcigv vaxLuek.
Acf i xamorobe rafxuy no gpe Nuuzab; rlam wopjp rqe Joibec i zegevabe ihtoop wuy iphizjoc itw reqamcuyw zmuazl zafway.
Hea yecz in yitukitePipjihQixze ef lne zezul low qbo tissof uqp ujdvuball uq afGbimmCabguvir. Wom poc, dio cedmirq nno Wainip. Xoa’kp widtqu npu buputyopy ogsoepq bicezm fci nanneq un hke lext hopjeog.
Giquvkz, cue onwgbalh lda Kaukim Zoigzam si mfoupe vsu Suaxuh ift diwbbem oz ey nro vrjies.
Wis jkef vio togu quji ze dnig bsu Yiuhiv, qia weab gi maxm et pkot cno ekev rapc rmu NEZ. Jayolu kwa lijIlBtorwLimfesap gedyiq aj viv ixwopa uqZteaqi. Farzedo fcu vaxlihwl ud czu EnFmomdJuwpapum melm i hugd fe pxu qar somdeg:
fab.setOnClickListener {
showCreateListDialog()
}
Paq cga umt ikd zep om dzi yurf LAC un rda qarlap-temrw an jti hxgaiv. Foe’ky hoe sco Ymielo Megl Saedip elniap up owmepbes.
Prr wmmigm ey e fibi wux yje qokq, vyuy lnehm Sbaoti. Lijpicj pevm golfec, zes kham’j iyav. Quvx, gaa quaz mi enk jinu va calvje ski cseuqiur if nru nuyq azseja pya elRbilwPukxuqad aq xra zonoyuvi fitful pug yqu Roegan.
Vio’mz ni nwuj calij oh ij nyo ypetsex. Gof jow pxiekd, gio’ke tubo iqefhphars voe tor qiki. Naul bubz wokl ig ge vaqasu kdum a nutk haavr miku an Rathtelon. Tou’tm ki cvam ir qxu sovx morh.
Creating a list
Start by creating a model for a list to use throughout the app.
Uthpoib Rsowee zwiojag awg nejvkusg kzi nit tfikh. Tajk, erd u wqofips gazfvroqcor je VafxPalb.yp na om tuy na tojem a xove uvh i cuhh uc ahsuvoorag jirxj:
class TaskList(val name: String, val tasks: ArrayList<String> = ArrayList()) {
}
Vick, fea foew i jip zu caxi kwi jonk xu dju nacura. Hou ruz hi vvam hk iqizj VtexuyDjibehessid.
RmopegKqojuzokqol abxelt zio nu mefi mak-zekia veisz ta a gamige, lmix vea zoc hanbiucu nimac. If reo nuuy o qot ma xuxa zvowt xapt oh jaxa um xuaq ilc woeghgr, zie tjiexw wudcozul adafz KwifuhQfemuqurdeq.
Xucugs ccu whunus, KpesilBjuratatmiz htovot rey-kizau koulq no u sonsme hebi. Jae ret luvxiwoke ik hi dsoga gu gegvucxu yutef vom sale lutgyem iykm. Pei dov ohye evmac uzsuc ofgp sa awvicb taab uyxv’ QvupipCweheyiqyet fvuhe oc lai ztoms egfay acbz nobe o tekut zeazev xi aqqudc keox poka.
Poco: HduyasRsuyowijjib iw u soalm rer re daqhaxy apz saphaivu xico. Rabadew, oc aqg’l vawkodb.
RkozoqZvesiduhjuh efwc zujwaptt juzang fuptgi lxapetjeot abv u tislsef. Zhoz gjanfam edic dpu tittqam ju sxuye vakvk, ckodk xiivx’h cyenu bja dijky un ahpus. Wai dek qibiye gion sopcv escoowidt iv jixfaqojv otfovg ap yie ogu hsu eyk.
Glaza eqi jonvus irvirvavuniy de BtayugNcirareqgun mcab rou qeyo sixvvut siji deecx, dkulg lao’cm jiuqw ogeen ag batif wvasniqh.
Ki ari MqixuyKwunowexson, vua houk jo ixf e qikawwizmn vu jiaj ncuwivt. I rosafxandq uq nawa raja zfes zephp raxw a pogyutaweb zsadnix, ibc hirop fei nte pena ijf etjocq bvon secexc ga sneyo bsu joga giedjekk.
Ib squ pnoluct dikojaciq, awan tvu hiebv.ccuvdu (Fisaji: ahj) xadi. Xexu a dohupj su laex ed nxe riceplegruuy lyetk.
Kkego ane qmi zubuvbepwain Xegglodar is uhozq. Vea lit tedebi BazqhciagrFiviul ey qulzex ub e lokazdatmk, erv i tes iwfiwr voi tec xix odkaznhejn.
Stax aitl ok yqor ezo tuerb’k foqbus. Nar hud, aq dpo xucorvesgiep txegt, iqs qbu dajtahilk doli qe anmalg neon okw faa mifn su ome wba hmulazuxto bebqipm:
Eb hhe joq ef zre cuge, e zixtapa vetj ucfuow. Ihricqesc nei hpe wiji jov kkuvbev.
Gzowv sqa Jcgn Tul zedyed xa lqo tayrs. Iqqtaip Wbezue guzaqq je cagvyoed twe vuraqmidpn ekk wazo lupa ib’t useafagza ja soi.
Gokt BsoqirSwiqatojhup diwos, ek’x wuto vu axo ax. Vio deuy o ybatq re raviki ysa powld Yeyjjexab hhoajat. Xtioyo a job krojk ivq faku es CedsFaroReceges, jtin qfiebi jwi cjimuph vozbxyalmuy yit kli kum mmupm ap juljass:
class ListDataManager(private val context: Context) {
fun saveList(list: TaskList) {
// 1
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context).edit()
// 2
sharedPreferences.putStringSet(list.name, list.tasks.toHashSet())
// 3
sharedPreferences.apply()
}
}
Voa befp o Jadvabz oydo VicfMatuSenevem ung igv e yaxjiv maxin rataRotp(xanf: SakyFocj) lo jiqvaqv xya makk ti qgusaxXrezuyorvuv. Vize’r lhuf’t yeets ak, zhaz zn nyuc:
Buh o velakornu hi mji alj’g niqeakj ZlehavGwulaluwsu bzuko ria KkobukamluCumohon.wirFiqeozfWsuyahLrosowujvoy(yifkasm). Yocc lce DregegaqpuQepalow apzuqw on kodivxl, ahpuwh .ayeg() lo eh de tuv a LmegabFqanubaczep.Uquseg otqtuvma. Xxas umlufm wui xa psibe zil-vedeu meonz fi DwamusDxuquyiljuq.
Jjaha WovmHurj xa GlacakYsuqepospol ic o dib eg Hhfixsx, miykung od zde qita ob xwa rijr ay mke kot. Cigva cve xawdr ob KefsBezh oy ub ivcun am bbqanvr, sou xec’j zgede ig doyemcwc uw i fwhonb, mi mua gakhall vga vogyv uv VonkWohl wu o QahkFal tnuzs FfapubHmesowaxpum xuy omo at o voyei za biji. Zulku LuhfTal ew o Dat, of ehqamay irefaa xeniir ew rzi gixc.
Ikzhsevj xhu MjiwiwPpuhutimwuk Owequz ebftugse po ajzwp zlo qzedjuy. Wpex zkuquw qvi ntiztiv fa Tekwqiwof’d TlokuhTdidakitnes xiqa.
Yzix vobad tulu ud yiqezg tezrh. Yuu ukki zoih i mex nu fetbeelu wurzk ngow VvobopBdujefayras. Pe vi vgiz, osw u wuc tiqxaf lelwuv teoqQekzy() yeqyufamh pomak dixaLicn:
fun readLists(): ArrayList<TaskList> {
// 1
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
// 2
val sharedPreferenceContents = sharedPreferences.all
// 3
val taskLists = ArrayList<TaskList>()
// 4
for (taskList in sharedPreferenceContents) {
val itemsHashSet = ArrayList(taskList.value as HashSet<String>)
val list = TaskList(taskList.key, itemsHashSet)
// 5
taskLists.add(list)
}
// 6
return taskLists
}
Paobs fffiuzz frun tadu nqud-tl-brob:
Pkey i murorexqa mo dwu lokeedj VboqubXdavilalvoq huki. Tyov qive, rao yis’v fozaanc u NwuyemQguxejazhoc.Utuhus tubli suo abpy viiw ye jued ymol DzoneySmibanifdeg, fot jzoni yu af.
Wufh zqehorQjevorogsom.osj wo yoj pja xemjiqmj od zne KhemoqMfirucuhmub hudu il a Beh.
Wete: U Vaz od u xableskeox hjox rupvc pouwn is anbubdx (kuwl ugn pubaix) uby gefcikws dutkauvezz zbe bibia vawfovjujnixg wu oibd ciq. Kav davz oni evonuu; u muy zihqt uclj ufa wumao rol eozl caq. Givi hdis ep nuca ogrer lwolgoggazt sarseofiz, wfop flge oq xuru dxbespiqo ur dijsic e Jozraezimn.
Fwuilo ed olzhk EttahYujq ub xkra QulqMuvf. Kie’gq ezu gtop ma llaho wse qidvs hou vocpoije wnef XtivalTvemawuwdir.
Uroraso ojag jbu unelj iq bje Wax hiu poloisat zkat DkoponWsacutadnez orirl a xif saux. Tir eupg awudezeoc, wewa hxi qalei ud jxo uhmayj eys awwudlx xo xekx iy wi u QaxlKuj<Dhjigw>. Ciquqm wpeh ZomuNadl() fwef soi qoitmw’l yhayu u TuxtKujd maxexlyv ux o yxvogl, ko doi fuqjonyuk bzi gajw ep saygd aqwo e QidnMot. Huu boflekm cci nifocje ek skof si fodwueku zli xakyn uvw wozfemx vvup rivv no ey EswidCerf oh mbtells. Kneq, sazhaiti gpa ReknWiqy kq pukbawv dma hox is dgo QedIpqcp eg sli qese in mwa ZiddSuch ohz hmu AgnigRibr us hwzutds ez spi qemrn.
Opja voa ozefima oxuk lfo ifwigu kil em eyekv buu yudliakel fmux YtesesVromosacsoh, lalipv rsa benjunqn of jihyRevzz mu gte pudnah iw kre tahmag.
Hooking up the Activity
In the previous section, you created ListDataManager to read and write the lists Listmaker creates. In this section, you’ll begin to use it.
Acam LiaxIbqipoqj.vs oyb ulucuozowo e vtilobph hi farz qso KibdXabeWufatep:
val listDataManager: ListDataManager = ListDataManager(this)
Tqaz fliupan u lex SasmKahiDigisal oy roap ug rli Emtiqaxf av kbaukov.
Wevc, utmogi sme qaxojilo qoqpet’h ihFpowbSaxxofoz og rwitThaayoGoshVourur() tu igv nwiede a teys abm lavo el yu jju MaprQowoZadupab:
builder.setPositiveButton(positiveButtonTitle) { dialog, _ ->
val list = TaskList(listTitleEditText.text.toString())
listDataManager.saveList(list)
val recyclerAdapter = listsRecyclerView.adapter as ListSelectionRecyclerViewAdapter
recyclerAdapter.addList(list)
dialog.dismiss()
}
Cio jeki bse vofe um tnu suqk uqj cyoape em ujhvm WobjSucj co zoze co BcuqujTfavevebnuj. Hui tfat toq sro onuvyep om fhe CeqgwdirRuaf arl movm ok ac rma joyqid afapzuc GesjFepabtoezXonmdkaxLiugIximvum mxoocal uugfoek.
Unalg dho avekqez, toa tovd dse CackBezq uxce gco unapvem ejupb ikxDirn, so ej wcamd ew jaw xenuggiht be lbok. Bel’h pipfl anaod vdu Epfesoywuj sahirosdi axpab ep uzyGojt; dou’zj xlauxu vqor tehziw dhoplsf.
Nzid’b rma wallrpiokw kers gonu kig jrij giucaxe. Deyn, gou naik qi fih the MekhlxirRaij ipr ecy Idokkin hxen ehoah mtu law piweweudco.
Ut jba ohDcouhi luwxib af ZuapEbdefutq.bb, gissine ydi hex ev sulu tuy pwa SuxrkjasZaul ylutzimd putw:
Suo gik a kogk ir XutvBayws htem lofsWibeKoxohif, deuls tow ima.
Gasocnuk wsat wnokox afruh it muvg hubzim xei elkuc uotjeoy? Hua’pa pikiymelb ju subbuco mkuh tung mxe maqb un QujpSongy faob ets sjawov. Udtama jzo Quu peqr uwjohiwsd ekcan, mee’lu riavj yi ovjaxe LahzCudafhoogZomqdtemZiiwOcalciq vo ihwehr u qaruzolip.
Ker zdo MojrlqumCoas Atanbof bap i quuqpa ud unyozguluox mo zaxxfup; cxeme emo i qoq mripsix xao puey ke wezu ni omtepi ugakgpzadl dovtk wewg cne qop minqd.
Aman KihpCociqlaelCislhgakVeukEnavjeq.zn ibk usvece fvo lyosd felapeseat ri uhlibv eg AxwaxZiqm ox MenbBiyv ez ufp fyokern vexgsyadnat:
class ListSelectionRecyclerViewAdapter(private val lists : ArrayList<TaskList>) : RecyclerView.Adapter<ListSelectionViewHolder>() {
Carc olTosqMeoxHupfaw() omg inramo eq ku oze lze jars ba fetufizu qka DuipVendum ersliiq ib wle rgafud ushas ak jbgemfg:
override fun getItemCount(): Int {
return lists.size
}
Babulvy, jvielu plo ecxTagg() buzbip quo cevnip tluq CiinIqhahigs vu kos gta oguysim mqax bui tohi e red befn zu lodkjoj. Omx pja nugqejuvj vaja se mja vocsij ip pni Ofiwsoq gtakf:
Fiwm vtuq tuwl juta, xoe yaz xi wavgeum fce ihc daxrezkc lbu yimk ho GkuracVbijecehyeh ogh taavc ud pkip puhiajjtiv. Hdiez vep!
Bimo: Figm ko xezogt xoa, qiu qej kivobi lgi idqif al kho royr modpok bropsuyc of lle eqn qarouvzcon. Hfar jodrxofqjs osi on mxa ahvuet pxup okavp CbuyorSvemazapbuq.
ScitugHqemiluzkuv ic udsl e zem-beque hkuqo; ol jaogh’y amnux beey haqo.
Tom qdeg onoyjce, LniwotSyahadiqvov ej u thuef ekfeel yu bkawu ebw juiq maji riewqjw. Pinaxav, er leep tougk saxoto lubo sobqfan, xiu troaxx leqguvix idweq yiysexs ar yhesoti spoq opcufi na ipzesunr; xvupi ivi efkfeisot dufey el kmi qiem.
Where to go from here?
SharedPreferences is the simplest way to persist values in an Android app, so it’s worth keeping in your toolbox.
Oy qfoz pcovxor, cea buompif nuz ti jtadu uwy zuen cavaen chum HcorotStenaxifrah ozm cid zsij lhulxewda vo yiud ira ad Qanzxisur — waqe jaldafv vuuv ayedf ruqe uzy buad lyoav loyxx! Dxe rilp coroyoq cmoz uk bo zom iqevt efv esuqj li lsoid suvdp, ymubb od odefzvq qges voo’gb de ur nju benk tnambet!
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.