package Ġcom . ak sh ay . news app . repo Ċ Ċ import Ġandroid . arch . lifecycle . LiveData Ċ import Ġandroid . arch . lifecycle . Mediator LiveData Ċ import Ġandroid . support . annotation . MainThread Ċ import Ġandroid . support . annotation . Worker Thread Ċ import Ġcom . ak sh ay . news app . App Executors Ċ import Ġcom . ak sh ay . news app . api . ApiResponse Ċ import Ġcom . ak sh ay . news app . model . Resource Ċ Ċ /** Ċ Ġ* ĠA Ġgeneric Ġclass Ġthat Ġcan Ġprovide Ġa Ġresource Ġbacked Ġby Ġboth Ġthe Ġsqlite Ġdatabase Ġand Ġthe Ġnetwork . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠYou Ġcan Ġread Ġmore Ġabout Ġit Ġin Ġthe Ġ[ Architecture Ċ Ġ* ĠGuide ]( https :// developer . android . com / arch ). Ċ Ġ* Ċ Ġ* Ġ@ param Ġ< Result Type > Ċ Ġ* Ġ@ param Ġ< RequestType > Ċ </ RequestType ></ Result Type > Ġ*/ Ċ abstract Ġclass ĠNetwork Bound Resource < Result Type , ĠRequest Type > Ġ@ MainThread Ċ constructor ( private Ġval Ġapp Executors : ĠApp Executors ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġresult Ġ= ĠMed iator LiveData < Resource < Result Type >>() ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġresult . value Ġ= ĠResource . loading ( null ) ĊĠĠĠĠĠĠĠ Ġval Ġdb Source Ġby Ġlazy Ġ{ Ġload From Db () Ġ} ĊĠĠĠĠĠĠĠ Ġresult . add Source ( db Source ) Ġ{ Ġdata Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . remove Source ( db Source ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( should Fetch ( data )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfetch From Network ( db Source ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add Source ( db Source ) Ġ{ ĠnewData Ġ-> Ġresult . setValue ( Resource . success ( new Data )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfetch From Network ( db Source : ĠLive Data < Result Type >) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġapi Response Ġ= Ġcreate Call () ĊĠĠĠĠĠĠĠ Ġ// Ġwe Ġre - attach Ġdb Source Ġas Ġa Ġnew Ġsource , Ġit Ġwill Ġdispatch Ġits Ġlatest Ġvalue Ġquickly ĊĠĠĠĠĠĠĠ Ġresult . add Source ( db Source ) Ġ{ ĠnewData Ġ-> Ġresult . setValue ( Resource . loading ( new Data )) Ġ} ĊĠĠĠĠĠĠĠ Ġresult . add Source ( api Response ) Ġ{ Ġresponse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . remove Source ( api Response ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . remove Source ( db Source ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġresponse ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapp Executors . disk IO (). execute Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Response ( it )?. let Ġ{ Ġrequest Type Ġ-> Ġsave Call Result ( request Type ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapp Executors . main Thread (). execute Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwe Ġspec ially Ġrequest Ġa Ġnew Ġlive Ġdata , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġotherwise Ġwe Ġwill Ġget Ġimmediately Ġlast Ġcached Ġvalue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwhich Ġmay Ġnot Ġbe Ġupdated Ġwith Ġlatest Ġresults Ġreceived Ġfrom Ġnetwork . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add Source ( load From Db ()) Ġ{ ĠnewData Ġ-> Ġresult . setValue ( Resource . success ( new Data )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Fetch Failed () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add Source ( db Source ) Ġ{ ĠnewData Ġ-> Ġresult . setValue ( Resource . error ( it . errorMessage , ĠnewData )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprotected Ġfun Ġon Fetch Failed () Ġ{} ĊĊĠĠĠ Ġfun Ġas LiveData (): ĠLive Data < Resource < Result Type >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Worker Thread ĊĠĠĠ Ġprivate Ġfun Ġprocess Response ( response : ĠApiResponse < RequestType >): ĠRequest Type ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġresponse . body ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Worker Thread ĊĠĠĠ Ġprotected Ġabstract Ġfun Ġsave Call Result ( item : ĠRequest Type ) ĊĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġprotected Ġabstract Ġfun Ġshould Fetch ( data : ĠResult Type ?): ĠBoolean ĊĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġprotected Ġabstract Ġfun Ġload From Db (): ĠLive Data < Result Type > ĊĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġprotected Ġabstract Ġfun Ġcreate Call (): ĠLive Data < ApiResponse < RequestType >> Ċ }