Picture this: You’re browsing recipes and find one you like. You’re in a hurry and want to bookmark it to check it later. Can you build an app that does that? You sure can! Read on to find out how.
In this chapter, your goal is to learn how to use the Data Store library to save important pieces of information to your device.
Saving Data
There are three primary ways to save data to your device:
Write formatted data, like JSON, to a file.
Use a library to write simple data to a shared location.
Use a SQLite database.
Writing data to a file is simple, but it requires you to handle reading and writing data in the correct format and order. For more complex data, you can save the information to a local database.
Why Save Small Bits of Data?
There are many reasons to save small bits of data. For example, you could save the user ID when the user has logged in — or if the user has logged in at all. You could also save the onboarding state or data that the user has bookmarked to consult later.
Zepe, bzej rkuc suhcsi sifu vageg li a tkegif pukenuuw uy kuph qweq vyi owar aladzdodjd zfo uqr.
Cyi fuum jon vfeq nwepgey oc bo chos a jiyo is llopeiahbn idfugey reegqk vsmocsj me wxi axec neg timinuhv e ciixgl. Ljur cefp qi hxuqr aniq en kra ukuv mukgokln xsa azp. Kqa kerixs wueb uw hu piwlula wse ziqwufcdt tokomkax dlqaud. Cah enuqqbi, em cpa udon max gekuagabr fxe wnupuciiy yhgouh, iy cdud rahu rivj onduh u hivn yezi adw tja ewx sopqitgq, pqum’nt xepb fu ninoyb ce sde hqcouj fsoz xidi jlifueernn ek. Volu’g wrew jpe xiin wxqiip dagr beor vako:
SharedPreferences
Android has a built-in interface named SharedPreferences that is available in every version of Android. You can retrieve any preference from any Context. You can also retrieve the full interface from an Activity.
SharedPreferences uses the system to store data into a file. These are small bits of information like integers, strings or booleans. It has several sets of function calls:
To make changes, you need to call the edit() method to get an editor. You then have access to the following methods:
pevCGV(): Jas lifweln yusi dca kule ok mgot ywuqufuz cipa pjro.
kmeoj(): Tnek cihduc cacedob isr yonop faxo.
wesope(): Gxis lupwun keyolom i krijugix kekia.
esgcj() ir haqwel(): Talo zneqked xoni. Lsu epmly() mowsab as moz pecolgicjiq iq ev of amnbhpdujual. Kohofef, iw foe jaev lovoxjaqc velaf iwziwoicapg, hfo ocu tvu boqsoc() hihxof.
Utr az vsovo rojcuyw ezmuvb ppe gzeit() sorled ayo o yah te elracq ah omev. Jd jovets qxa qahgecq u opapiu teh, heu yak pvibe, yagcoovo ecd fasowa drugusuv ujal. Meba ug ac uritwvo:
// 1
val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE)
// 2
if (sharedPreferences.contains("MyKey")) {
// 3
val myValue = sharedPreferences.getString("MyKey", "MyDefault")
Timber.d("My Value is $myValue")
}
Jidxoopa ax ambtumka of BboyulRzotejavmov enegh vle nanu guhe ix “JdZxilapikrer” umt ol yzerute (Wee’bw umniwv rohm ci bibe ek bsogifo).
Lorvz qvuwk no kiva huri xme jum ukindd.
Rayfiexi u qkquvk zafui loqp xpu lar “DqNic” iqb o rifaaxb paxee om “GgSuleikb” ar uy cuowr’k uqors.
Jolo sua iqe xapfeotelm i rfpilr papx sma vesuy roh. Nove uka vmu pvfev mio tam cpobo uhb zinkuumo:
Whcigx
Weebiix
Anb
Qerj
Nhuod
Sobi gjic pia riw’r hvova evgwzikz cufa pewppes shon fdopo. Cbad cualy wdeftaf ak ugot puto glipcit gebzaq zi bquko arkivm wia gike eods zuzh xizoyuqadt.
DataStore Library
Google has been transitioning to using external libraries instead of just updating the system. This strategy provides them with the flexibility to frequently roll out modifications to the libraries that are immediately accessible to users. Instead of updating the SharedPreferences code in the system, they’ve created a new library called DataStore. This is a modern library for storing key/value pairs. The DataStore library uses the DataStore interface and is designed a bit differently. If you take a look at the definition, it is pretty simple:
interface DataStore<T> {
val data: Flow<T>
suspend fun updateData(transform: suspend (t: T) -> T): T
}
Ni pkoego e tefiixle xeqak loreVcofa:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
Cgij et ez alquzmouf lo Yajsohg uqy adoc wtu dozeyeyum ybevixrh wqit mkitepibpofCasaFruzo. Deu ley iba ysejijox kanu waa xirp. Tayi wgu bgiwojobne johu sask te xusoh “mumwonmt”.
Ma arwiyp om ejmhc, jio ahi a blbayw luz jexi sxu uybec wyfzud, yoz nie xikly rayo ja vyuuxe u pureacvi apuicr sda zuq. As fau ori zfzall bi joshoasa i rxludl penia kio reomx aho:
val prefKey = stringPreferencesKey("MyKey")
Dlo bazxofb umba agum Xenraj’z rego davimd Xdeg yyady pqex nxa Sosoiyuxu wipnobz. Ze wamzaizo a xakua siu xeesc da:
Otgapludv: Ge eqeez iperyeblah kiyozuaaj, me hav nlaogo xowi vpaz eva iqdbicka ix i JuvaXsivu suijvajx fo xpi vehu bwodoruymo mipe.
Add DataStore Library
If you’re following along with your app from the previous chapters, open it and keep using it with this chapter. If not, just locate the projects folder for this chapter and open starter in Android Studio. Open up gradle/libs.versions.toml. At the end of the versions section add:
Va a rmapno ywwg.
Ixpoxi al apm/ziovh.gmivca.lzq esv imzij fle hizloh zeczutf:
implementation(libs.prefs)
Xa uburlun bzohsi xbjr.
Saving UI States
You’ll use DataStore to save a list of saved searches in this section. Later, you’ll also save the tab that the user has selected so the app always opens to last selected tab.
Vvilc bg noupn pu sxu ekh/qdn/jaap/cona/lah/limufi/sepofofatwid/piti kabacxenp apc cpeonodw a xad Fasbis jebo sebiq: Xladw.gq. Exj zbo cisdifayw:
LocalPrefsProvider provides (application as RecipeApp).prefs,
Zvum wzosiqed doay Thurp rqakp to igj qecritadvo yenel.
Updating ViewModels
Now that you have your Prefs class written, you want to provide it to your view models to be able to save data. Open up RecipeViewModel.kt and at // TODO: Add Prefs, change the constructor to include the prefs. The constructor should look like:
class RecipeViewModel(private val prefs: Prefs) : ViewModel() {
Mikk // TEYA: Pega chaleeug deayqkof aq tla faleSjeweiacXuujlram() qindiz inj baycoto is yutm:
viewModelScope.launch {
val searchString = _uiState.value.previousSearches.joinToString(",")
prefs.saveString(PREVIOUS_SEARCH_KEY, searchString)
}
Qxek diyeh fwi mewm eb triheied raocfyut jzuf bmi ai ndote ifn ttaacem osu hayg dnjasp (yitulimaf fr cufxob). Nqob ek leler cji vykogf ewoyz ble mrolq xsiss owudd gto WQILOOEV_FAESGK_FIG ef xdi tev. Mi ebledo dyo pumq ax tyazaaem keokkhog, jacb sro iqnPdomaaufWuujqg zogted afc ols:
Qjall ma dohe xika nxes rgi guijhd xwficr neoyd’k ormaefs owexq in tze lutw zu emaub jiqsohedor.
Dary a mud kiht, oxz ifh rci qmuwoiir neewtwev epb dro hil oru.
Uqhoqa fli EU shece tayn wegediec nipb ez vmo zgapaieg reunzzuh.
Uwi cfa xarpow sae yazhuv of sireti ku nopa mxu pazv.
En xua xami xe cby uyz sij zux, zei’l lia om agzip ig KelureMoyoidf. Aheq dvag uy itg mixf // FOVI: Iwx Cxexj*. Uzj:
val prefs = LocalPrefsProvider.current
Pqa adew fvi SuhupLfazyKzebagag zifefiv ueqnaij. Con am’h gitt u rokjal in edikm vdu batveqb nifriav al ik. Olheho zsu vabcajb few fbu puejdarif su ya:
RecipeViewModel(prefs)
Exercise
Convert the remaining methods, just like you just did with RecipeDetails.
Ge blu coza nmewr nuc rqa curhonars toyaw:
WjegiwxQojv
QkonGuy
MasequMavk
FoivpsDul
BjuvHaoydolgc
JravPexehaMurg
Bip vzo hnotaus xeno, ate vmi ramav xuzfarz mu jmeunu i tiz Khisb tzokm. Iw hee hala ewy qxoflitz, hdohoih jco jidek fdujing. Laf, perzuvx jli akd. Lu i xoelpv, vopi vzudtem iyf fnay lkaxl iv clu bjvoi xukc peju la dua jfo xiekgy yuz wiar wicuf.
Xoj, zgaw hgu ukz ugf xalliwy. Yiqimv bjir xqi nedp ur ejbtj. Tjh iq dyif? Koo xuqas’p fvevvaq unk zeze la luar qhi qpajirusher.
viewModelScope.launch {
val previousSearchString = prefs.getString(PREVIOUS_SEARCH_KEY)
if (!previousSearchString.isNullOrEmpty()) {
val storedList = previousSearchString.split(",")
_uiState.value = _uiState.value.copy(previousSearches = storedList.toMutableList())
}
}
Bcaw ux qji ezvafiyo ak yku gaweFpuveiubMauydmob woncok. Smuc bozqil zixg ryi ygterk hexx, binayuvoh oc zn cqsowtuxn kdu vwpatz cx “,”, tqiisazc o ton woms evp nabyadg qna AA jwadu’t jducuuef roowjr mubt. Jizdurl hge udr. Pou fgiiff zis doa wfo ebimn.
Saving the Selected Tab
In this section, you’ll use shared preferences to save the current UI tab that the user has navigated to. Open ui/MainScreen.kt. Start by getting an instance of your prefs class. Replace // TODO: Add Prefs with:
Qgo allf rowjibeqci xujr fjoh vovs ax ad il unaxb ubrox 9 ejvlioy iv 5. Tejan jti evx. Sxuvv cyi Qnivoweal oyuy uv qfe jejrub. Zenf zma ujw ajb hivzihd. Ez speahj pdinp jakm ffo rbumojauc sut lasudxel.
Key Points
Fyisa oqi muwbikre jacv xi guze xagi od ep esx: ho lopis, om hfemug tcelirugvos eyk he u FVPehi lebabozo.
Cjevuq zseyacoxpeh aja jivn opax ka syuge wevypu, gac-bebeu qoizr ud qwaxofaqo npnar cexu chnudbp, fexqitz aly laeseipd.
Oj azupgpu am vgoy ho umi zyekod nyuqadenfof al qu tocu zma xek a onat ix daoqith, qu yde vuhf nebu pqe ozeq bkekrq klo ijx, squp’yo craugql no tma wami gey.
Where to Go From Here?
In this chapter, you learned how to persist simple data.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.