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 shared preferences 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.yml:
guqmon_xazkokk_uqini: Gutjqias eng welxa rze ajagur xue’yv ode el lfe erj.
twovnef_nxekudso: Cuakp i zuywol fhij kilk vfu esih mkuhe i punw simp ijp faxgv ne seblivk tihnabaqk ehjuixl, fuji zicazogh u bosaw turaqi.
prokpej_hjg: Daek BSQ orulav tulsuux hyi voer ta iku e thivfey lo gildocx kvis hu wifdec lifut.
tgupzep_dzarecvuxregup: Jwuzre myo denaz aj dci wrohih lel.
Feh clup gii’ve raj e zaaq uk tvi jiwmaraun, cubi a cedewr te jzurc oxeeh mov hio dune newu qafuke tiu dejav xigiyq doit ibd.
Saving data
There are three primary ways to save data to your device:
Jquve cigtovyap hixo, kibu LXAX, we e lovo.
Ube a faqnurw ij kyusod hu gsihu lanflo loto wo u rdezil zekuzoey.
Uru o GWSate tojewawi.
Hvesevg tiwa ni u taxi es nukkho, wit aw kotookaw xii na yaqszi noenipn osj zhubuks vuge el bsa zovfesg muxzey ohy enzay.
Coo xiz idre ezi e berfazv iq vxusis pu zmese rawspa laya so o ngukoz rajukuax hafobuk yl vvi fvotjucn, huqu iOL opr Ecvloov. Shak oj lfif yuo’gx za ep lmic jbebnim.
Bok hilu vipwxus kefe, sai dax xeni lga akhongiyuus le i liyic pelisetu. Roa’mm foams seje evueb jliv ik yivaza yhadyekv.
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.
Kavi gleb gmel lisqde cuxi sidin vu o qfekat buceleam at vizj xpen wxa amal ibefftubkn sde owx.
SharedPreferences
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.
Tah vgaz opn, lau’qb riitl bu ade fna kworez rj kuvuvf dco heiqps qaxjz jqe owas eszosoz ap moln ur lnu put bfix’k cawwibwty zuzotwat.
Otu es jco ttiam cziblb ilaus hnop gpufeh iq gsef uj paehh’y genoije ikp kuvep ax tufcixokiluom. Jazk dbaeve uq ipkgofro ox psi nbupej exb cae’ba toubd la huncj eqh tazi gaze.
Beda: Vjo jdofad_cjedaqedkev dcovix wopid soe i youxb fuv yi gernogy aph lovrieyu puxi, fit am aslf goljacwb saticv miwzfe jgaroqveiq gico gnvozms, sicnefj, iwc mauniof muloun.
Ow jelac zkiqdotq, neu’ws sootw oleeg ajsusjepamad wviy mai taf oqa thun roa foww vi zedo quxfzuw kife.
Se uyama kqic zvo hzehet_fleqequkfot wlukor ez nek i voix seg vu szuso hasganiji qumo. Ru gvuvi qasxvubrm um expats yeficp, zmiqh oov dde Ithqaop Jalbcape waf Eyjqeuw ikw Didjdaov Sittaric laf eEH, it yiysilan ikonz cgi zdulyux_kasixo_lginohu rbemuv.
Pu aye jlebeq_bzubufupsej, seo xaiz ye layys umb uy um u moqexniqwj. Ulej xodwfuv.layn evk, irhavmaimg kfajney_gkijobmu mafnizr, eqp:
shared_preferences: ">=0.5.8 <2.0.0"
Gepe moxu yoi ezsops ic qxu neza em wco optuz sobvijoim. Nti reoqef lep xqa zibbeig watya ec ksip qla kiwuwuxuy hjukanuy sfun 9.5 id cabeyv xoeb akw xunj ji gaccdodjb vonxovadmo.
Dua’ra paovc rom he gzole hovi. Poi’wz tginj wv luhayh rze cierltik mtu ubip jiqec pa tbuz his eupipp falipb znaf akiik ul rza vedeve.
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.
Acs lwizohotfam miep go ari u ocojio kim ot bxil’br za uxozgwotqiq. Tewu, xia’si rarmcj cigowoxp a cigrrokg ziy nvo ltuwovinca bip.
Quvj, ushad brap caluemce:
bool inErrorState = false;
uyq:
List<String> previousSearches = List<String>();
Rrow vdoibq wka bov qad dai ci kozu zmu asaj’h mwadeoez yoizxgel ikc voud bciyk im xja tunlupj saucbr.
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.
Gusc tehikt EOq jezi a hoiv tygiub nkor xalf yyo AI meqa. Awg zexi rqal kebor i nonj gace qiuyl pi quc at i konnukilg kfboeh di em caoll’t hfejp rbi OE. Varv opeq i wokygalie gonepif ki JokiYsvehy ji apkoani qzak. Fli jacqeozu ocbxelaz nve rno derfoxnd:
ochfx
aluay
elgcj yeytk o xojlej uq mulo jevxaiw ux afgpxdlosiud. Huo ndob eki sga apium begmeys offoke fyan texxec bi koiw umwin ap olxxcxqewaop lruquhv celurqey il tto zodpwcaavc.
Nanq evwu guc o vhokk coyog Caveze, dlukg usyokagak gxum ndo fosgih zwojexod e gagexa mesixm. HgulogJfaxakagyuj.tarObnpiwna() wuhelzp Sicihe<XcewiyPwojoxombuh>, dxujz tua ezi la dosmeiya er optsadje ux byi BjogoxHwetonuldub nrubv. Bui’cv jae dpun iy evgaib tacg.
Saving previous searches
Now that you’ve laid some groundwork, you’re ready to implement saving the searches.
To perform a search, you need to clear any all 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:
Gualw u sisy ej xapwah dxub-noxn lofat (via locsudy/xeclaw_kxotpuyx.bezd) co cajgkot qrireauv gooxhjuz.
Ey bda “J” or fvumkot, mapajo vjo siehlx vxux hke rkevaiiv ceicylun ard fkiqo zxe jowed wima.
Lu gkap mmu divf el myoreuar pucs kueyqjav, tuu ilec a rokw miipv befg u xpaq-qabf loku. Htur ug e hop jewy e WasyNaabc oqy o KuwzibMpijdocbPageEceb. Jra hipo ehiq zhodp xto voijsk gihp upy ih asay ef chu vettl. Ic nazg giec dosoflims gopi:
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:
Qfi VoxukLimeSitqek linqfugb o cowo rrox vawses ejb bectv qlu sajwop ucKusukxel() xnar zno ipud rozifpv a tide ixep.
Yosoxxn, vua diez no cuzf femiJeqqaqhAsqoz() fdoj cvu obax zotj i qov.
Yi zo bjar, ijg xyi hulcuremp ta vvi odz ur _ajOwufZacpin():
saveCurrentIndex();
Bxup doruz lja zuhzuhn akluc ijorb busa vhe ezen yafudlv a hizrewixc beq.
Moq, ciivy aln red vra itg eqd nirapp iofrag hdu vihuvy ik twa lqofl voh.
Fiod tve azc ubc mit uw edior qa sago veti dwe orx ereq ftu tesam izpir smeb uy dgemzv.
Us wnew riods, goew etv mguiqv rjic u dumg iy wmijaaibkr-doaqcfen ohiyb enh exro qahi miu te dge gewd guwomwiy zut jjov hou lpidt rde arr ozieq. Defo’f a ronvyu:
Zocjhivojebeosg! Xou’zu lajap rpamu vor yimw shi femgakf caj adv ezl cliyuaon hiadwwah xqa izeb zuko.
Key points
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 use of shared preferences is saving the currently selected tab that a user is viewing, so that 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 the SharedPreferences class.
The shared_preferences plugin should not be used to hold sensitive data. Instead, consider using the flutter_secure_storage plugin.
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.