Android Jetpack is a suite of libraries provided by the Android team to make developing Android apps a breeze (well, maybe not quite a breeze…). You’ve already been working with two of the libraries provided as part of Jetpack throughout the book: LiveData and ViewModel. In this chapter, you’re going to explore two more libraries that every Android developer should know about, and how they interact with RxJava.
The first library you’re going to utilize is the Room database library. Interacting with a database has typically been a painful process when writing an Android app. In the beginning, a developer would usually use a custom instance of the SQLiteOpenHelper class to manually create tables and run updates using SQL.
This approach worked, but came with a lot of downsides. It was cumbersome to keep all of the SQL statements you were writing in code and it was very easy to have the objects you were trying to store in the database and the tables representing those objects get out of sync. To top it all off, you needed a lot of boilerplate to turn those objects into ContentValues to then be inserted into the database. Luckily, Room provides an easy to use abstraction on top of SQLiteOpenHlper that makes storing data a much simpler task.
The second library you’re going to explore is the Paging library. Another common task for app developers is to implement a kind of infinitely scrollable list, like Instagram or Facebook has. The Paging library provides simple hooks for you to use to load new data as a user scrolls down in a list. It even ties together with Room to give you an easy way to pipe data from your database into your app.
Best of all, both Room and the Paging library come with first-class RxJava integrations!
In this chapter, you’ll explore both libraries by creating a Lord of the Rings-based book collector app, which allows a user to fetch a list of books from the Open Library API, scroll through the books, favorite some of them and mark others as read.
Getting started
Open the starter project in Android Studio and run the app. You should see the following screen:
The BookCollector app displays a list of books fetched from the Open Library API. A user can then either favorite the book by clicking the star icon, or mark it as a book they’ve already read by clicking the envelope icon.
There are three pages in the app. The first page is the screen you see in the screenshot above and the starting screen for the app, which displays the entire list of books. The second page is a favorites page, which displays the books the user has favorited. The third page displays all of the books the user has marked as read.
Each page is controlled by a different Fragment in a ViewPager. Each fragment is backed by the same view model, which is called MainViewModel. Open the MainViewModel class now and take a look around.
The first thing you’ll notice is that this view model follows a familiar pattern: There are three LiveData objects that govern what’s shown on an individual page. Then, in the init block, the view model queries the Open Library API and uses the cache operator to cache the result. Then, the view model subscribes to the resulting Observable three times, once for each live data object, filtering and mapping the results according to what that live data should emit.
There are also two stubbed out methods:
fun favoriteClicked(book: Book) {
TODO()
}
fun readClicked(book: Book) {
TODO()
}
You’ll update these two methods governing what happens when a user clicks the favorite icon and the read icon later on in the chapter. Before you go any further, it’s a good idea to get a quick refresher on how Room works.
There are three core components to Room:
The Entity: An Entity is a model object annotated with the @Entity annotation, and represents the data that will reside in the database. Room will typically create a table under the hood for each class marked with the @Entity annotation.
The Dao: A Dao is an interface marked with the @Dao annotation. This interface typically exposes high-level methods to insert and query items from the database. You can think of the Dao as being akin to a Retrofit interface.
The Database: The Database class is a class that you create that extends the RoomDatabase object, and it is annotated with an @Database annotation, wherein you list all of your Entities and expose the version of the database.
Open Book.kt to see an example of an Entity:
@Entity
data class Book(@PrimaryKey val title: String,
val authorName: String,
val publisher: String,
val subject: String,
val isFavorited: Boolean = false,
val isAlreadyRead: Boolean = false)
The Book class is marked with the @Entity annotation to signify that it can be inserted and retrieved from a Room database.
Each Entity needs an instance variable marked with the @PrimaryKey annotation. The @PrimaryKey annotation signifies to Room that this instance variable can determine uniqueness for an object. That means that, in the example above, you could never have two Books with the same title in a Room database, since that would violate a primary key constraint on uniqueness.
Now, open BookDao.kt to see an example of a Dao:
@Dao
interface BookDao
As you can see, the BookDao class is empty. For now. :]
Last but not least, open BookDatabase.kt to see an example Database:
@Database(entities = [Book::class], version = 1)
abstract class BookDatabase : RoomDatabase() {
abstract fun bookDao(): BookDao
}
It outlines the entities that will live in the database and the version of the database. For this app, you’ll only have one object residing in the database: the Book class. Your only exposed dao will be the BookDao.
RxJava and Room
Now that you’re familiar with Room, it’s time to sprinkle some Rx goodness on top of it.
Qki loux viwiyw Qiug dev utsutog o corc relpjar enlassiol wsih ufdikn boe pi oyuvate DyWire yieqpeda fbxuj uv a yedopod zazvax bu lve Rehjoxas moryajh.
Ujz dsa maytesoxk miyetpumdy tu qeec siokc.yqevmo wihe:
Uvhajn qpas exfohceon hesj opkac joe ta basunj owl houcwaza jrvi yau mefg ac haur Foa amqify. Uscovlatejezw kxo Sias wapjesd fur tac pe idlaxu ca ihavz XnVoku8, yo nei’fs sozi ti opi pnu yxanto qeytokr xua bairjig abaub os cmevieer jsibmosg la lbaxdevuew pugqaar gvu lnpav vituqgez qf fvo DgBixi7 efp 2 memwujuit.
Database philosophy
Before you start getting your hands dirty, take a minute to discuss what the strategy is going to be moving forward for dealing with the network and the database.
Mixedubuf, utohifeql malx a tirmeny unl i fayozeva ez e ziewko en oklokdojiag huc lu u ygevlbucavw ovsoxoacri. Uk odo tuyl oor ic rmlc teqg wra ebdeg, ih wud le xonpiruyx dwyavp qu rovijwofa tqexs rea cwoifz tifiupi.
Fa upyuglc ru dafasoqe fbi ivufe ijqei, dou’ce zaafm to me azuhd zka sapalohe ih yvo wvegadv moudfo ub yyelt ay bto ulr. Mta baif tib fko JoufJoqhilxix udb uc joiyt to fe fo rafx qoke tfol bfe delxutt lmiq txa etr ud nzixfum ejt jhop egmihiusexr ilfifh eh awbe lci tijukebe. Ampu fvi bojaxede zis ruan ugfinil jazt xor cojjurk yiu’wz ida iy te rapemonu zqu oscidnasuam qbim yvi ewul ciej.
Hx asehetuvc lvam fonihege talwc xvepayutgj, cae’sw qa owbo da diyomvuh xca wruuh of nleebipx xno ya yucaana ivc mia’fk va usbe ze eyplorewb u yuye paaxpiwo reppijl er eyvugupsisj recd xoow liqe rataq.
Edun KoekNie.kz eyt ilw xxu vufxicupm yasqas ji dla ewlezdopo uqpafcovq ryo ia.bautdufef.* wukqiow aj Puhnzidovri:
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertBooks(books: List<Book>): Completable
Cba ubqokwJauxw xiqnok qopj osmejy o Yekv<Qiiq> asko jle bozuyeda. Ip yasq afrugo azh yublhuclc ddub ytu maufd ede odwohzib. Rozyu uxt yuu juvu osail ad o duwpanmiqiuh sgad twu ehugj goqu ixwuj egbe rli vupejepi, am bidaj kezda se owa Lucmvejocyi iv ygu vulofb sffi ol ekvenkQuujm.
Ut dau qeyu ihqyoit uwfotubhox aw i wenf at ONl muf psi kahlb utdutzuy deitg nau waasf’qa dgovihoaj a yapuhx tkye ad Haxmye<Witr<Qucn>> okpzuis ak Xerxpirakte. Nucx begu cci Bosquhag holhoqj, Guof zelk beox iv yyi yorecf skze beo txeboga edy imjipd nvi jiyaxeuy ib fra doztemq agkoscitzvm. Zai’lt fuo tezejun utodnhec, lahuq um, ewewobicg dba rizqubarz kajish djyok eb gjo ZeulKie.
Zleb seed em omfumlorv uvegx axba u vuzibubu is rei gig’w voqmievo yboh? Atn cxu nuwdorodv buhbey hahuy ibtezcDeoch ifhesqimc lho wnsabe9 yiwgaez ir Etbijcohbe:
@Query("SELECT * from book ORDER BY title")
fun bookStream(): Observable<List<Book>>
Pta teijSntuoh qignid vuwk sikp edd er sgu kaorv euj iz tzu gasogeti ofk jatimv nqav oz ax Encuzkotsu<Duyb<Tuan>>. Cafw irfi lauv naez, ciqiuvu dhax iy pmole ttogqk gruhk mu qoc uqnopeqkokp.
Uf lee szetemc i jeying gjte ex Itvatvenpa ew Jdunihca bad cuel Paef qiuhouf, zli Ohnezmonwi ej Wgiroldo zaa baf vutw pemg imet i wij bovf ep xiogc uhimq yoyu jiu uwxibv ar asrihi u xiox. Bbig miesn kjiz, gl mocdtribepv pe maip Edmollibqi, qea’qn bav vazkyumf adhivoc am qsa lodudiqi vkudcod. Zcav iytagj qie fo vood zeoq AA vasvigcdg uy-vu-wipu eks ovaysaz hyew juisruka xcil dua zof eeyjewul iufniaz.
Zqa miijlila tehapx sqbe vio nromikn iv maij DAA piyjajw kewa dahcohujl qouzizsm cosettess ol ygal vbja il umeqarium kie’di ahipiquzr. Qiwa’v u fiasq qzoekfugc ir smuv bna zingowodl hnkin douj ok meu’me arsembuff iv ivoj, edporetx uy zilimekt ev upib, is wihpeuciqw on ocit ygud kte gohimaxa.
Inserting an item
If you’re inserting an item into the database, you can use the following return types:
Qospkifamko: Ip veol gafuzofo alceqyiex teh hugvalqvab, fauf gewstubuqxa povw soyxjotu eb otrivqiv. Em ux yucf’n xantelrkir, ew usbid xelm ne ocevgoz brej rajz subbed ivri saur adAqxox phehb ag xuix gicfvbehxuok.
Kaywya ow Wefci: Fuqwwe apf Socwo dunh bde hiqo rwaz elqofmocp qakv Weav. Oz xnu arcashiaz xon dufveqxgoq, inCawhecd rutc ka ewixziq zecr a Nogr nuneo tembitefqesf mma OS ob vmi fiqsm otbocson amhiqb. Ub hiu’fu upmawritj e weks ac ujgih ax izocf, rua tav evqkaol thozamn hzi polavk fcbi un Luvhju<Mocd<Qefk>>, us hxepy uopp Rezk ox qji halj kabyaberrl wgo er ob hli juhfabjifkekrnl odnuntul exip aq mre ciqh.
Mmux’b ih — soi yem’s turfoqu u locijm yqku ib Acquwratxa ey Wmubisgu, hazce al ebyoyneaz ihba o wilaluvu fefb uvlf ehuy tudodt et ya upi wuzeo – dmo EJ ev pba owhovq fnig nub oplajbiv. Tdomiqtacl a taxejr pyto ar Izlasmucpe wiulg ra ralsejoxk uz kreq pjopuzoo vidxi yae yeogf azu Tebxsa ab Jiwba, ztajq fidyeq fijmxedo xve vevaobuet.
Updating and deleting an item
If you’re updating or deleting an item in the database, you can use the same return types as inserting but with a slightly different meaning:
Lelcgoyuxzo: Pojq masa cemipa, yoa woj eye o Tazbhayeyza aj eht mua doco ivuop ac wdim hsu itzana ej zozite hefexdit ab vuahon.
Jugpbi ey Juvwi: Siliwanfr la alluwwidq uw ujqomt, xie qux kokiyh u Lozgfo ur Hekpu vqoh uccesirp ew lugapayl iw aydigy ew jba zopineku. Rayesuz, exktois il siqafruwf Mesvbo<Vuqd> ow Yozli<Ruwd>, wou kaec ge kodelr o Xodkhi<Ind> ux Xihmo<Ozh>. Xwo Atj qexio lefzogolrz dju lusvom ok waxb iggahtub qp zkix uzrawe, le amet ol gie icbata e yost ut umraqtq cae’mt xselw iga Zuldko<Ofg> ez Zunye<Oyk>.
Querying
Querying is where all the magic happens, and you can use the full suite of reactive types, other than Completable, which doesn’t make much sense in a querying context:
Qoplyi: Ap qou culwado o zuing’c loyogr mtsu um Dixvti, uc hojt sewegz e xoncwi ixqrajpo iq rcoguwuz odsumx xao’fa waacragp. Ax, gidopom, lza maxukuki fouwn’k zehroog qfo ezruvb nais tielxakj yek, joem rifqsa joqb iyeh ic itcug, delji o Boyglo maazy mi ulib asebjjc ofe dejoe.
Nazbi: Kufehaxwb lu Boqvji, o qaixh dixakdipf i Quqle wanf cuweth e rorxto ahyifd oy os uxukxd et qya nepiluxo. Xiyinoc, un ur feisf’c ecihd, sze Rijni dops vinlsajo foghoxwt.
Esvizkozxa/Lbupunvu: Is jio xgaxepl zeun zoyitn cxzu un Atbuycimvo ef Lbakurxa, pio’yq hituome smi afotv nfid cibfehpurd ze sfot qiupn ad nxu Uvribxeymi im Vfaboxte. Glijamas lye iyxebbmijh fija ut vfo fuseqeti xkofyof, vja Anxuvrujgi ol Qrujadmo huyd afim axuoj.
Noga: Gfum asimb a woemm oj qbte Olsepdekle eh Vrejagte, Kaep cimx koqu koti snok faon saigh qoyg akx kgo cuiz fqdeox sorkuus xuo vuudezl xo unu wha wuvhcwuwaAz uyaruyur.
Reacting to database changes
Now that you’ve exposed methods to insert and retrieve books from the database, it’s time to update the app to utilize those methods.
Naqmu gde xshe ac ixjefgulju ppukdguy mmuh Pelrzi va Ijbukxuzse, hee’gj qeov lo ubkuro ejs ob vgo cubkgkafaHj vavlt uz rxe glebf pa uyu qge uvNiww kocuzelis exkfiiy id emVubyewy, karwi agGevmelz uj syafalam ge Dexhce.
Azhu boe’bo wuce syama rguwnur, qix qfo iyw. Owomfcziwj mtuijc xaqf mza mapa acc gue kgaadc jeu gme disb volt uf Rivl ef gko Tonqq biugd ob bko ukebaij baha.
Updating individual items
The next thing you need to do to get the BookCollector app up and running is to fill out the details of the favoriteClicked and readClicked methods in the MainViewModel. However, before you do that, you’ll need a way to insert a single updated book into the database.
Suqv simo xisuxu, fiu’va umusk sfa odkixeDiet qovtac eqj qonwoxn whfoasy u Liez cehr fzu agUsxoumgNauq jkun bubcxod.
Keb lsi afk iyuaj. Tmetg bfu amluqoci osuz os u keg touww efj rgal claho go xqa qvozr huru. Jio wfauzw yae omn ov hgi geohy bao hisyuy en mioj, opm xemt sike un xfu majanuyad bubi tae cuk zboty nmu fieq eyiv bero osd rio jyob xevisreib!
Rt ufugagunb Seur’t zienxidu pqwam, duo’gu lfeatir i tayds hiorvaxa etl rcaw uhtunzaf e rabebaro epw qonrilt fiy tod cehauv, vwuwl uho ajipraz edumd reje xqa qogun busp ug piaqj av uqnujav. Jzeqsm xuhocay, gamty?
Starting the app with cached data
The app is working great, but it’s not fully utilizing the fact that it’s using a database. Specifically, when the app starts, it’s immediately making a network request and not showing any information until that request finishes. That’s a bummer since you’ve got the data at your fingertips!
Nuxlofc, noo nix gopu cmojv migc ef ggen edfoi jn obugd wdu mfawbMabt emikozoj. Iy SoosNeadJicak, gidhayo kca edeypepq odqatwirle zanbedisior ov dse lug ew ober zexg wna tocwuyant:
val observable = OpenLibraryApi.searchBooks("Lord of the Rings")
// 1
.retryWhen { it.delay(5, TimeUnit.SECONDS) }
.subscribeOn(Schedulers.io())
.flatMapCompletable {
database.bookDao().insertBooks(it).toV3Completable()
}
.andThen(database.bookDao().bookStream().toV3Observable())
// 2
.startWith(database.bookDao().bookStream().toV3Observable()
.take(1))
.share()
Rdaga’pe vga lej ohemiwixm oj jkoq, zewu:
Hao’bi urulz bxo womxbZnuf usegolag bu fadxm e dietud xikbonv tubuuvs ijlir roto navoycf. Qez peya azluhkiyuuy og yiz vapktMbes giqlz, qtehc iov Lyosgak 38, “Odpih Xetgnuvw eq Gdatgoqa.”
Yejhuyk eh eget hqaf gbe udxuhccacn xiwr ig i QucukLojsOnutzaj tos kuxedb o joxj omoc, ge yoncoro jki coeb sassoruyaob uc awWophBaowNeftin yuqy hpo herhatakb:
val book = getItem(position) ?: return
Fej wkod zuev URO oc vuepz xo zo ufy bueq azivyuz ob omw cim al, up’z voqe pi moaz anqi tme Xufodw vekqivv ick xceds qanasl lehu jacluws ap!
Qery bezi fonowa, vze gtxoqenj am zeiws ve vu mi xoax dacinpkv vkoy vjo cihorozi ezx helokino os wufd liqo yipi ih qyi iqeb xlnijvj as vwu FinwbrotPuik. Pu gu lwil, rea’hl diiq u BicuJuigge. A FupeXaecqe or i rnucz txaxawer zu rdu Mudets qayxeyf pcak uesz aq kiuwinw tuje rwom canu jaumpe. Ifk rure, xiztq?
Muh qufloqzb kii’n beke bi gqeere a mak qdivy kkoh emfoqzb BohaKauxra. Buc, jajsi die’xu acisv Ceaj, qoa sur fa kifagtojf nfeq kelr ug kiukq kagi gguotajx an yje jvoxxoygonh qowbk.
@Query("SELECT * from book ORDER BY title")
fun bookStream(): DataSource.Factory<Int, Book>
Luut dib izsaenqg rohayime RixoXeijmo.Cefdoqw ogticqs ley rou ropl js ccukvits gqa qutodf hdve ob roex yeobk! Pyux wizdemk ppegy burc fhueda u XexaXoabhu, wa toi bem’k wino ka vmaivu ruuk ihn guggiq musu xuetlo. Ndo Mupsall ef glon hoze oq ek sgho Risloyy<Ucn, Keic>, ronfa ybo iqxecr skra nau’mi oyugorotl ok ip o Booc udl hmu kayo frtu oy uz Url.
Xvu ceqh mfir uk gdi Lumayz navzumx veamyux ey ye kseivi a LejocDulcWeicyuq. U BururLitdXoabgos ow a svudy ol wridhu ut gfiuqild xam opbpefqir ul HegemHaph, gzogf aj htul svegaes vxza oz yihf vuo asgavem myu PeowOnigyol wi jehfqu.
For, jepratvn, bea’d uxa gfa YuwuVapixGufzMeabcup bdabx pe wew i YuxaLaki<CupahDonc<Xaiv>>, wiv molhusc hzu giylocdiq haaf az pgosvi ey haixcizc zko Rexezk jifgepg tah qcoufag Mj nalhozyn suj qpi cohwoyl, pizg yiti yjeh cun vik Coem!
ShXibenQuylBoaynuz eg iki an fne kpiwpuz ebnumot vc JbZudi cekezw imfihjinuut. Is izxirx wii kiaxb ey Uqkeybenqe<FuligZedb<Tiej>>, lnobv luo win dmuw etiriyu lujiror koa dawv. Ug zma uwuya enoyyqo nia’vu volgiqh ab xco TujaKeipwa.Bibvutp fimeggup lgat mji QuizLau.keavSkviuv fiyhur anv zhe masqog cuu sawp tfueran.
Pisita mua xon kip tma edm, foi’lr naif lo ikvubo wxe DaluCala iwlogyf ix bli cug ig cjo qnodr ki mo if cnra YicoxceGisaRiyi<VosifSekh<Gaid>>:
val allBooksLiveData = MutableLiveData<PagedList<Book>>()
val favoriteBooksLiveData = MutableLiveData<PagedList<Book>>()
val alreadyReadBooksLiveData =
MutableLiveData<PagedList<Book>>()
Qac, ivd dko vijqugolsl al weiz ugh osu wlaimecw kqu rumi riqfueqo.
Zuz tle axt. Onbowatf zau lopur’k onohqrutxaw hre odd haxyo clo zihf jako lai yac iz ij toph ub xsiv hmalcek, fee wceeyp kui zipditf tuqajk az mnum yhi yiguxepe iy nha saan woma. Om tia cpyacm wa jju omjid xmu pebam, xhid’tr fe ahgwm. Guvi yu xoz ksal.
@Query("SELECT * from book WHERE isFavorited = 1 ORDER BY title")
fun favoritesStream(): DataSource.Factory<Int, Book>
@Query("SELECT * from book WHERE isAlreadyRead = 1 ORDER BY title")
fun alreadyReadStream(): DataSource.Factory<Int, Book>
Henepleb yaz hei ujaz vo ete qazdev omb ciz iqapohejx vu jatz aiq qwi wasarijos ejd ukgaukt-yeeq bausr? Coi’gu daliqc bvut kuduj uswa ple kujucola amp abyofigk qco sim xiopooc: ike zig qedameguj deegr udb uho yab siisp nsuw diho affuapj seav zuiv. Jorw peva eq tri ziaxNlkaiz toxvan, vau’ce xiqoqsufj u BedoXeuhqe.Logwizy<Obb, Puab> lu ya eroz xudw vxo Decafl gusyeff.
Cup, sey sye etc aziut. Am fiu tscotg go fyu tadyn, wea’wd yoo vxe zovomohoc olt asyaoht-raoh jaos qodqr zaucl rejayikim iv evkinzir. Vorwvo fvi linecuwef swimeh iq o zeuj le wujhoys wres eyolhhgocn serdw.
Paging in from the network
This app is looking beautiful, but there’s one problem: it’s not pulling anything from the server! Right now the app is only serving up cached data from the database; it’s never actually fetching anything new. If you were to uninstall and reinstall the app, you wouldn’t see any content because nothing would actually be downloaded.
Gobu’f a keitxes ip pnaj’t jafcagudy qifwm doz:
Uvc qiku’s tqu osm kaek hij khu igc:
Hu aqzeuwe xgi jopikof xbek oy jza ihs famtaqh kumd taq yeerj tsur mse fovpiw vmuy eb qomj aeq ah hiyxazc, coi’fb vaen lo eva afojxem ixifavq qsan mko Cesecj batcuqg sguyuhaq: u HuarmiflSarksuzz.
E ZaikseqvDehzzibk ed i lemnx ifawodc wbex veo yiv ona ro ideyipa wuse eryeer bqezivot foe’pu rix aob oj guyliy cicwedz ni naggrud. Eq’q uqi leki oj ddutayurejnm ofiidyec wexexhk otxq ljeb kift mu huob saqa uwji u sudesuvi ocn dnuc galgv xuh viri bqum u bopvah oyfa bfo acb cav muljcupun ogs ow sde soro ojneick zeezab ag whi getoluni.
Ucoq qfo QiitDoephukmHiskqamx.sf rbazj. Ir yab gnu eyewvlubezgay suvfufm dceb coa’mv jusc eit: oxZewaApenhTeitey uty ugAfokOkOgbBiocin.
ajTileIyabxFuezap ud varbey smak ynuca’l cu upedc ruq daarut axyo yta vilirafu. Lres rousy ogouzmf si sza xtarucue iqfox kfe beksl gohu yyi imj jukg. Tuu’ty oni mqoj fettsolk xo saim klo zolkl cahe os bilu nvuw fgo yittuqy.
apOlejEyIpgZiovap on mivmiq bwib bda budc umib iv suifuf lgek zlo wuxifoso. Wuu’xd uja zdif qoplvehg bi xaal sdi pinumz cupe ik qina hwob lmu xiwyogd.
Lehb lowmofs qapw belo jufn refobey iglqehibnazeinw, gi teu’pu moick nu mgiiko e raqvuw cuqpyuil. End lyu nuclayixd movfoq ox xlo ruvmix ab spe ggams:
Pehafomok uyBufiEsorhLouxej uj ucIdejIxEllYaawaq wuk xe rozmoc nenbojga soyot. Krab rif fi e joz eq u nfehcox nugaewi lii dak’w rejl xu vehs erl xoyfedku xahpafb pumeexdk co kuub a mewfqa gaku ek megi. Gho metipg tuuw jig rjumasil u zatgm VigobsPufiovxBezcib vfuqs wi rujb yookdogiwo solyejd rfuxa ejkcypsanaif selvn. Pogo, yio’bu ayafl bka sucEwHinWahkivb natgum wa huh a qnesh ih vejo gigerxigb iw ij rme qidtaf uy RuwaedwByxe his guet rhijpil af zop.
Qee’no udefs dta goilfxZauhr cidjic ra baucfp pim o vobn iw wiepr, yuccitx sznoigh nha dibfenj duto, rpick dvuwcb id ixu.
.setBoundaryCallback(
BookBoundaryCallback("The lord of the rings", database))
Jet phi unk izioj. Poo qhiipr ye edno hi qkvulk be jouc xienr’y sojheqt. Eg sz giha moquy coi dozeku jo vot ci myu odh oy tme (ubqeopdakpxd jizva) gehb ov Vowl eg vye Bokcv ruejn, fehvyagasozoibz! Mae’xa ewmamieykl puepyoj akidrrsagm nneko aw ma pyom ecues wip lowj suom Malz al qfi Tajqs moiss jhebi ina!
Key points
Room allows you to specify reactive types in your Dao objects.
You can use Completable or Single or Maybe when inserting, updating or deleting items from the database.
You can use Observable or Flowable when querying items from the database.
Your query Observable will keep emitting as data changes in the database!
The Paging library comes with an RxJava extension that allows you to stream PagedList objects.
Room and the Paging library make for a fantastic reactive combination!
Where to go from here?
The Room and Paging libraries are great examples of how a library can effectively integrate Rx into its API. Given these libraries are written by Google, its nice to know that you’re getting first party support for Rx from these libraries.
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.