/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 0 7 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġn lab . practice . jet pack . ui . paging Ċ Ċ import Ġandroidx . databinding . Observable Boolean Ċ import Ġandroidx . databinding . Observable Field Ċ import Ġandroidx . paging . DataSource Ċ import Ġandroidx . paging . Paged List Ċ import Ġandroidx . paging . Rx Paged List Builder Ċ import Ġio . reactivex . Back pressure Strategy Ċ import Ġio . reactivex . Single Ċ import Ġio . reactivex . dis pos ables . Composite Disposable Ċ import Ġio . reactivex . rx kotlin . addTo Ċ import Ġn lab . practice . jet pack . R Ċ import Ġn lab . practice . jet pack . repository . Image Pool Repository Ċ import Ġn lab . practice . jet pack . repository . Paging Item Repository Ċ import Ġn lab . practice . jet pack . repository . model . Paging Item Ċ import Ġn lab . practice . jet pack . util . Resource Provider Ċ import Ġn lab . practice . jet pack . util . Scheduler Factory Ċ import Ġn lab . practice . jet pack . util . Toast Helper Ċ import Ġn lab . practice . jet pack . util . di . activity . Activity Common Use case Ċ import Ġn lab . practice . jet pack . util . lifecycle . Fragment Lifecycle Ċ import Ġn lab . practice . jet pack . util . lifecycle . Fragment Lifecycle Binder Ċ import Ġn lab . practice . jet pack . util . recyclerview . paging . Binding Paged ListAdapter Ċ import Ġn lab . practice . jet pack . util . recyclerview . paging . positional . Position al Data Load State Ċ import Ġn lab . practice . jet pack . util . recyclerview . paging . positional . Un bounded Position al Paging Manager Ċ import Ġjavax . inject . Inject Ċ import Ġkotlin . random . Random Ċ Ċ /** Ċ Ġ* Ġ@ author ĠD oo hy un Ċ Ġ* Ġ@ since Ġ 2 0 1 9 . Ġ 0 1 . Ġ 2 9 Ċ Ġ*/ Ċ class ĠUn bounded Paging ViewModel Ġ@ Inject Ġconstructor ( ĊĠĠĠ Ġfragment Life Cycle Binder : ĠFragment Lifecycle Binder , ĊĠĠĠ Ġprivate Ġval Ġpaging Item Repository : ĠP aging Item Repository , ĊĠĠĠ Ġprivate Ġval Ġpaging Item ViewModel Factory : ĠP aging Item Pract ice ViewModel Factory , ĊĠĠĠ Ġprivate Ġval Ġactivity Common Use case : ĠActivity Common Use case , ĊĠĠĠ Ġprivate Ġval Ġresource Provider : ĠResource Provider , ĊĠĠĠ Ġprivate Ġval Ġtoast Helper : ĠToast Helper , ĊĠĠĠ Ġprivate Ġval Ġscheduler Factory : ĠScheduler Factory , ĊĠĠĠ Ġprivate Ġval Ġimage Pool Repository : ĠImage Pool Repository , ĊĠĠĠ Ġpaging ManagerFactory : ĠUn bounded Position al Paging Manager . Factory Ċ ) Ġ: ĠP aging ViewModel Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġsub Title Ġ= ĠObservable Field ( resource Provider . getText ( R . string . paging _ un bounded _ sub _ title ). toString ()) ĊĊĠĠĠ Ġprivate Ġval Ġis Show Refresh ProgressBar Ġ= ĠObservable Boolean ( false ) ĊĊĠĠĠ Ġprivate Ġval Ġis Show Error View Ġ= ĠObservable Boolean ( false ) ĊĊĠĠĠ Ġprivate Ġval Ġdis pos ables Ġ= ĠComposite Disposable () ĊĊĠĠĠ Ġprivate Ġval Ġpaging Manager Ġ= Ġpaging ManagerFactory . create ( paging Item Repository , Ġdis pos ables ) ĊĊĠĠĠ Ġprivate Ġval Ġbottom More ViewModel : ĠBottom More ViewModel ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġlist Adapter : ĠBinding Paged ListAdapter < Paging Item Pract ice ViewModel > ĊĊĠĠĠ Ġprivate Ġval Ġsingle Scheduler Ġ= Ġscheduler Factory . single () ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġbottom More ViewModel Ġ= ĠBottom More ViewModel Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlist Adapter . is Show Bottom Progress Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaging Manager . retry () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlist Adapter Ġ= ĠBinding Paged ListAdapter ( bottom More Item Ġ= Ġbottom More ViewModel ) ĊĊĠĠĠĠĠĠĠ Ġfragment Life Cycle Binder . bind Until ( Fragment Lifecycle . ON _ VIEW _ CREATED ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubscribe Paged List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubscribe Load Start () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubscribe Load Complete () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubscribe Load Error () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfragment Life Cycle Binder . bind Until ( Fragment Lifecycle . ON _ DESTROY _ VIEW ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdis pos ables . clear () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsubscribe Paged List () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconfig Ġ= ĠP aged List . Config . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set PageSize ( 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Pref etch Distance ( 2 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Enable Place holders ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĊĠĠĠĠĠĠĠ ĠRx Paged List Builder < Int , ĠP aging Item Pract ice ViewModel >( create DataSource Factory (), Ġconfig ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build Flow able ( Back pressure Strategy . BUFFER ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ Ġlist Adapter . submit List ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsubscribe Load Start () Ġ{ ĊĠĠĠĠĠĠĠ Ġpaging Manager . state Subject ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . state Ġ== ĠPosition al Data Load State . LOAD _ START Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbottom More ViewModel . show Progress Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlist Adapter . is Show Bottom Progress Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsubscribe Load Complete () Ġ{ ĊĠĠĠĠĠĠĠ Ġpaging Manager . state Subject ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . state Ġ== ĠPosition al Data Load State . LOAD _ FIN ISH Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ Ġlist Adapter . is Show Bottom Progress Ġ= Ġfalse Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĊĠĠĠĠĠĠĠ Ġpaging Manager . state Subject ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . state Ġ== ĠPosition al Data Load State . INIT _ LOAD _ FIN ISH Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ Ġis Show Error View . set ( false ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsubscribe Load Error () Ġ{ ĊĠĠĠĠĠĠĠ Ġpaging Manager . state Subject ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . state Ġ== ĠPosition al Data Load State . LOAD _ ERROR Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ Ġbottom More ViewModel . show Progress Ġ= Ġfalse Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĊĠĠĠĠĠĠĠ Ġpaging Manager . state Subject ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . state Ġ== ĠPosition al Data Load State . INIT _ LOAD _ ERROR Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next Ġ{ Ġis Show Error View . set ( true ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetList Adapter (): ĠBinding Paged ListAdapter < Paging Item Pract ice ViewModel > Ġ= Ġlist Adapter ĊĊĠĠĠ Ġoverride Ġfun Ġget Sub Title (): ĠObservable Field < String > Ġ= Ġsub Title ĊĊĠĠĠ Ġoverride Ġfun Ġis Show Refresh ProgressBar (): ĠObservable Boolean Ġ= Ġis Show Refresh ProgressBar ĊĊĠĠĠ Ġoverride Ġfun Ġget Banner Text (): ĠString Ġ= Ġresource Provider . getText ( R . string . paging _ banner _ to _ count able ). toString () ĊĊĠĠĠ Ġoverride Ġfun Ġis Show Error View (): ĠObservable Boolean Ġ= Ġis Show Error View ĊĊĠĠĠ Ġoverride Ġfun Ġrefresh () Ġ{ ĊĠĠĠĠĠĠĠ Ġis Show Refresh ProgressBar . set ( true ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠNOTE ĊĠĠĠĠĠĠĠ Ġ// Ġinvalidate Ġíĺ¸ì¶ľ Ġìĭľ , Ġìŀ ĺ ëª » ëĲľ ĠìľĦ ì¹ĺ ë¡ľ Ġrequest Position ĠìĿ´ ĠìĦ¸ íĮ ħ ëĲĺëĬĶ ĠìĿ´ ìĬ Ī Ġì ¡´ ìŀ¬ ĊĠĠĠĠĠĠĠ Ġ// Ġë¦¬ íĶĦ ëłĪ ì ī ¬ ë¡ľ ĠìĹħ ë į°ìĿ´ íĬ¸ Ġìĭľ , ĠíĺĦ ìŀ¬ Ġpage d List ĠìĹĲ Ġ 0 ìĿĦ Ġì§Ģìłķ íķ´ ì£¼ ëıĦë¡Ŀ Ġíķĺ ìŀĲ . ĊĠĠĠĠĠĠĠ Ġlist Adapter . current List ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . take If Ġ{ Ġ! it . isEmpty () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . run Ġ{ Ġload Around ( 0 ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġtoast Helper . show Toast ( R . string . paging _ notify _ refresh ) ĊĠĠĠĠĠĠĠ Ġpaging Manager . invalidate () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġadd Items () Ġ{ ĊĠĠĠĠĠĠĠ ĠSingle . from Callable Ġ{ Ġadd Items Internal () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( single Scheduler ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( scheduler Factory . ui ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Success Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresource Provider . getString ( R . string . paging _ add _ item _ un bounded _ format , Ġit . first , Ġit . second ). run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoast Helper . show Toast ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addTo ( dis pos ables ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTotal ĠìĿ Ħ ĠìķĮ ĠìĪĺ ĠìĹĨ ëĭ¤ ëĬĶ Ġê°Ģ ìłķ íķĺ ìĹĲ , Ġë ŀ ľ ëį ¤ ìľ¼ë¡ľ Ġëį°ìĿ´íĦ°ë¥¼ Ġì¶Ķê°Ģ íķĺëĬĶ Ġë¡ľ ì§ģ ĠìłķìĿĺ ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġ[ ìĭľ ìŀĳ íķĺëĬĶ Ġindex , Ġì¶Ķê°Ģ ëĲľ ĠìķĦ ìĿ´ íħľ Ġê°ľ ìĪĺ ] Ġê°Ģ Ġì¶ľëł¥ ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġadd Items Internal (): ĠPair < Int , ĠInt > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnew ItemCount Ġ= ĠRandom . nextInt ( 2 , Ġ 5 0 ) ĊĠĠĠĠĠĠĠ Ġval Ġrandom StartIndex Ġ= ĠRandom . nextInt ( 1 5 0 0 ) ĊĊĠĠĠĠĠĠĠ Ġval Ġimage Total Size Ġ= Ġimage Pool Repository . getSize () ĊĠĠĠĠĠĠĠ Ġvar Ġstart Choice Image Ġ= ĠRandom . nextInt ( image Total Size ) ĊĠĠĠĠĠĠĠ Ġvar ĠstartIndex Ġ= Ġrandom StartIndex ĊĊĠĠĠĠĠĠĠ Ġ( 0 .. new ItemCount ). map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġindex Ġ= ĠstartIndex ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġimage Index Ġ= Ġstart Choice Image ++ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠP aging Item ( index , Ġ" New ĠInstant ĠItem Ġ- Ġindex Ġ: Ġ$ index ", Ġimage Pool Repository . get ( image Index Ġ% Ġimage Total Size )) ĊĠĠĠĠĠĠĠ Ġ}. run Ġ{ Ġpaging Item Repository . add Items ( this ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠPair ( random StartIndex , Ġnew ItemCount ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonClick Back Button () Ġ{ ĊĠĠĠĠĠĠĠ Ġactivity Common Use case . on Back Pressed () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate DataSource Factory (): ĠD Factory Ġ= Ġobject Ġ: ĠD Factory () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġcreate (): ĠDataSource < Int , ĠP aging Item Pract ice ViewModel > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Show Refresh ProgressBar . set ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġpaging Manager . new DataSource (). map Ġ{ Ġcreate Paging Item ViewModel ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġcreate Paging Item ViewModel ( paging Item : ĠP aging Item ): ĠP aging Item Pract ice ViewModel Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaging Item ViewModel Factory . create ( paging Item ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . nav Count able Paging () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ }