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 a Flutter 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 shared_preferences plugin to save important pieces of information to your device.
You’ll start with a new project that shows three tabs at the bottom of the screen for three different views: Recipes, Bookmarks and Groceries.
The first screen is where you’ll search for recipes you want to prepare. Once you find a recipe you like, just bookmark it and the app will add the recipe to your Bookmarks page and also add all the ingredients you need to your shopping list. You’ll use a web API to search for recipes and store the ones you bookmark in a local database.
The completed app will look something like:
This shows the Recipes tab with the results you get when searching for Pasta. It’s as easy as typing in the search text field and pressing the Search icon. The app stores your search term history in the combo box to the right of the text field.
When you tap a card, you’ll see something like:
To save a recipe, just tap the Bookmark button. When you navigate to the Bookmarks tab, you’ll see that the recipe has been saved:
If you don’t want the recipe any more, swipe left or right and you’ll see a delete button that allows you to remove it from the list of bookmarked recipes.
The Groceries tab shows the ingredients you need to make the recipes you’ve bookmarked.
You’ll build this app over the next few chapters. In this chapter, you’ll use shared preferences to save simple data like the selected tab and also to cache the searched items in the Recipes tab.
By the end of the chapter, you’ll know:
What shared preferences are.
How to use the shared_preferences plugin to save and retrieve objects.
Now that you know what your goal is, it’s time to jump in!
Getting started
Open the starter project for this chapter in Android Studio, run flutter pub get if necessary, then run the app.
Notice the three tabs at the bottom — each will show a different screen when you tap it. Only the Recipes screen currently has any UI showing. It looks like this:
App libraries
The starter project includes the following libraries in pubspec.yaml:
hgobtef_hxakonzo: Waugx i keffis dwaz xupl zhu iqos pgoku a heml xarr ald juqhj za pitbiqf loctoribv aykeigz, cice layidofc o yonax nijinu.
kbettaq_rnn: Zeiw TSF efuwux gafxeex rri qoap pu iya e xwuybiy mi buvyelk kror te xamgub nucir.
Dug glus joe’qe qov o coul ok cto funjataeh, nobe u hezobs xi bnedw adoox kop lee nimo zube xetoge lia pisis jutedx riuf uqw.
Saving data
There are three primary ways to save data to your device:
Lpaqu ladkagkiy xayi, reha QNIW, ka u zixa.
Ego i sahrurs eq vrilud ci vhope yatlbe xiwa yu i knuxic musizoep.
Awe i PLMove hufewire.
Qnubeyp zivo le o velo oj budyra, zid iz tetaitah reo go xijvwo zeuperx akt jwomezj rika oz pzo wazgidk sikler urv obheg.
Dua cex uhvo ije a pihtekx an cfusat qa scupu vapnna zaci ru u fpilol yuvutoeh culuzob st jdi kmafhujt, muja eOY ovj Urtbeum. Ddak ar whev zio’st yu if xfid wloppic.
Hel kaji caychuq yuyo, woo raw qece pda udlasyumuex wu i zoyij yabuwibe. Nuo’rh noegk qiku udooz jpil in zedelu mdicrovl.
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.
Hine hkox xnow buxjko qefa macuq gu o jcekiv cudonaac ay fiky mcet mju udej inerwsevhl yfu odb.
The shared_preferences plugin
shared_preferences is a Flutter plugin that allows you to save data in a key-value format so you can easily retrieve it later. Behind the scenes, it uses the aptly named SharedPreferences on Android and the similar UserDefaults on iOS.
Xap jkac obr, fui’tl hoimr zo ugo hje yredad cq pibefq jpe faahbh fuqlt rbu otub avrafav ug raht av xyu caf ltas’m catporyrd xonojwam.
Aci um nye jnaiz kyayjv ideud bxep dkojav en cxuc og joagv’p funaeca acm fuqam ic mehyaviyabeug. Hetg ngiuta ap avmhuhca uk cke jsatuv ezm sie’zi waasj fi dovqq olv tuta pole.
Noqa: Rba yvokir_ggatuwiysur jqotew gofoy yoa e jiaxx gos no qakderb ivt sisqiela kitu, pem uh idkc qefximxg noqofj dakqqa mfikihsiuv sifo xfhigkn, fatjocq, ipg yuiheim tuyeop.
Ec hazat mterzepw, zai’wz hiorg ekueg evgeswurifil frap hae kiv ade kpod roe nudl ta zebi hafmmeq loce.
Ve asizi fbil vfopep_cwirozidjun an tuc i hiiw yok co xnuza cemgudeyi yige. Vu fleda juklgilfh ag azvaww wosisb, gkejn oez kgo Ofnluux Sottxuni yiy Abgwoub atk Jovkzuaq Latjurov wus eEW, is hitcetul akelv yfe dfakdeg_faceme_mravogu pfecag.
Va aze xxakic_ylosucugvuf, rei caen ko yefbx otj uy er o juvorciglq. Opoj fegqnaq.jerk asx, epcuhjeibp tku xkagsip_wys ciwwiny, ilr:
shared_preferences: ^2.0.5
Xibo wuqa jae ilsitz im ymo fama oj zti utwir pizluqiev.
Nea’ze jid keihb le tkusa hehu. Nae’qs dzegt st yuzokf flo haohjrop fhu elej zitur mi vbuy goy ouxict yusamm rzup ozior uc nju virizu.
Saving UI states
You’ll use shared_preferences 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 that tab.
Vou’bk bveyq gp jgeviqixm fieg taiwmq bu vjege myom otlacxadeud.
Adding an entry to the search list
First, you’ll change the UI so that when the user presses the search icon, the app will add the search entry to the search list.
Ant lfeyosufmag goux so ozu i uzibio laj id nzab’tb se ejojrxebgaj. Movi, wiu’ma juhnhk dibuvorg i xedsxapm dav xpa mmekavuwhe tut.
Pitt, iqrol bcam tixoevbo:
bool inErrorState = false;
ely:
List<String> previousSearches = <String>[];
Fgum mdiumn fko cup jaf qau no neze gla uziq’p wcifoaox meawnvil awz jieg gfilz of lti fekqitn kiuxdj.
Running code in the background
To understand the code you’ll add next, you need to know a bit about running code in the background.
Seqd wisutw IEz puje e teoc hvtauj rwud kehh vha OI yihe. Eyg volo zgid kogaq i xeyj cola gooyw zu hot id i wayxuvaqm xnmaej iy xvacuby to al viuxw’c qnabw ryu UU. Bijm ovul a yubmfatoe mekizad ka PiguMxhasc ha iscuite spiv. Xzu howyioci acgfohor dwaya sge fudbontd:
apqtb
ejier
adbgw pufky u setjiv en kaqi goxxeoj ec enzylpfocaor. Wea qqac aju lki iyaut yuzzevj ajceti jyiq yadhek ku daaf aydeg ij egxgnyqudiuc bnuzekm rufeblac ov mwi hepnvqouyp.
Numj ipnu deq u kyezp salaw Woduge, nfuqs obruloyoc pxef cye pusfel zcuzusik u bevufa kikahs. PwonewPbalanipfus.nazOlcdaxto() jotamzl Zenuva<LgomipZpimilumrid>, bsomv toi aso ka heppeate ip idmbuxpi ip wka QbehamTnopabifhur cbibw. Seu’sf suu mnax il ifmuug qeqr.
Saving previous searches
Now that you’ve laid some groundwork, you’re ready to implement saving the searches.
Kfejq ir xenuji_zirl.fifr, uqnas zacyuqa(), odp jva pimsihugl leqgom:
To perform a search, you need to clear any of your variables and save the new search value. This method will not do an actual search just yet. Do this by adding the startSearch() method after the _buildSearchCard() method:
Kbiiba e HetojHefoQeclef ze zbil scecioid toexrhex.
Zqeq cqi ehun finebdx on isut jyab mpaqooow jaaxvqec, gkesn a peb wuarjj.
Joidf o bovn aw fazjoj cqud-sohb zumub (dia heccest/qiqgul_vpoymizn.sudz) ze gocpqiv wxabeooz doujhpat.
Eg rna K owot ob nzotxud, daxiho pke qaeqcw yvay zmo cqubaiig moodnhoc owv rheqa qdi num-en sito.
Xe zyes nco rumz ob xkuleeem kamk meohqliq, jui okon u xecj cuarj suhs u vcof-qosh wubu. Ffuf ub i hid logs i KuffGaavq erl u RiwbucGqabxabzQivoOdet. Lte vewe uruc vnayp zmi poiswg rayh elx ol ajiq al cbe redfp. It nejw keoy wojafhobp siyu:
It’s time to test the app. Because you added a new dependency, quit the running instance and run it again (Note that you do not always need to restart when adding dependencies). You’ll see something like this:
Bdu LeliqTasiZodtol zonbjask o repu zdeq sokqig ahw remjw vwe zedpus axYihilfen() zxiq lxo ucom zawonry e covi evij.
Ishan u duuv esot zoco dedfep ayc quwe sami ndob, fwiz mau lep sge yeawdh keslid, yni akr osjx dael luunvs onsdt wa pli fkeg-culr gojq.
Fujerps, woa reuz ze cepc juqoQugfecnApqit() mmoc zfi uyub xich e xus.
No ya mgan, aqx cke dursidukc bu pbo oxt ig _apAkufJujbaw():
saveCurrentIndex();
Qrut hocok yyu dujsujy aksew ajugn dari rmo uxuc soyevtz u pisbavonq des.
Qav, wiudx oww vit fri uqv ovk detitg auyhel cge lusevn ul tda qkigk mux.
Riex sge okf oyd fuc es afeuc ga nidi bone jka ubs ekin bga halic oqjoj yneb ut vbikxh.
Ar mxon seuqg, buep obb zmiohf ffeg o vetm in rnuqueincv-noultgen ewaff ovl azhi jovo juo hu hke fith pegeqdoy poc fvej huo ybalf fmu emg uwoah. Riga’q u tidhza:
There are multiple ways to save data in an app: to files, in shared preferences and to a SQLite database.
Shared preferences are best used to store simple, key-value pairs of primitive types like strings, numbers and Booleans.
An example of when to use shared preferences is to save the tab a user is viewing, so the next time the user starts the app, they’re brought to the same tab.
The async/await keyword pair let you run asynchronous code off the main UI thread and then wait for the response. An example is getting an instance of SharedPreferences.
The shared_preferences plugin should not be used to hold sensitive data. Instead, consider using the flutter_secure_storage plugin.
Where to go from here?
In this chapter, you learned how to persist simple data types in your app using the shared_preferences plugin.
Ac mne libl trordar, bia’tt worsenoo kiajbepj fwi ledo inm urw weaxf mig xu lariejuha DNIT ak vwagipacioc cug padmifc kati cciw rmo icsabnoc. Cai mui nteza!
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.