/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠAle ks and r ĠK amy sh nik ov Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// 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 Ġname . er ax ill an . an il ist app . ui Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . view .* Ċ import Ġandroid . widget . Toast Ċ import Ġandroidx . core . view . isVisible Ċ import Ġandroidx . fragment . app . view Models Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġandroidx . navigation . fragment . nav Args Ċ import Ġandroidx . paging . Load State Ċ import Ġandroidx . recyclerview . widget . Divider Item Decoration Ċ import Ġandroidx . work . Work Info Ċ import Ġandroidx . work . Work Manager Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . flow . collect Latest Ċ import Ġname . er ax ill an . an il ist app . R Ċ import Ġname . er ax ill an . an il ist app . ui . adapter . Media ListAdapter Ċ import Ġname . er ax ill an . an il ist app . databinding . Fragment Media List Binding Ċ import Ġname . er ax ill an . an il ist app . data . room . Media Database Ċ import Ġname . er ax ill an . an il ist app . model . Media Sort Ċ import Ġname . er ax ill an . an il ist app . ui . adapter . Media List Load State Adapter Ċ import Ġname . er ax ill an . an il ist app . utilities . INIT _ DATABASE _ WORK ER _ TAG Ċ import Ġname . er ax ill an . an il ist app . view model . Media ViewModel Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . util .* Ċ import Ġdagger . h ilt . android . Android EntryPoint Ċ import Ġname . er ax ill an . an il ist app . model .* Ċ import Ġname . er ax ill an . an il ist app . repository . Preference Repository Ċ import Ġname . er ax ill an . an il ist app . utilities . NETWORK _ PAGE _ SIZE Ċ import Ġname . er ax ill an . custom views . Result Fragment Ċ import Ġjava . time . LocalDate Ċ import Ġname . er ax ill an . an il ist app . utilities . auto Cle ared ĊĊ Ċ const Ġval ĠARG _ FILTER Ġ= Ġ" filter _ fragment _ argument " Ċ const Ġval ĠARG _ SORT Ġ= Ġ" sort _ fragment _ argument " ĊĊ Ċ @ Android EntryPoint Ċ class ĠMedia List Fragment Ġ: ĠResult Fragment () Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġbinding Ġby Ġauto Cle ared < Fragment Media List Binding >() ĊĊĠĠĠ Ġprivate Ġval Ġargs Navigation : ĠMedia List Fragment Args Ġby Ġnav Args () ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġargs Constructor : ĠMedia List Fragment Args ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ` by Ġview Models < Media ViewModel > ()` Ġis Ġa Ġlazy Ġdelegate Ġthat Ġcreates Ġa Ġnew Ġ` viewModel ` ĊĠĠĠĠ Ġ* Ġonly Ġthe Ġfirst Ġtime Ġthe Ġ` Activity ` Ġis Ġcreated . ĊĠĠĠĠ Ġ* ĠIf Ġa Ġconfiguration Ġchange Ġhappens , Ġsuch Ġas Ġa Ġscreen Ġrotation , ĊĠĠĠĠ Ġ* Ġit Ġreturns Ġthe Ġpreviously Ġcreated Ġ` Media ViewModel ` ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval ĠviewModel Ġby Ġview Models < Media ViewModel >() ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġpreferences : ĠPreference Repository ĊĊĠĠĠ Ġprivate Ġvar Ġsearch Job : ĠJob ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġval Ġlist Adapter : ĠMedia ListAdapter Ġ= ĠMedia ListAdapter () ĊĊĠĠĠ Ġ////////////////////////////////////////////////////////////////// //////////////////////// ////// ĊĊĠĠĠ Ġoverride Ġfun Ġon Attach ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Attach ( context ) ĊĊĠĠĠĠĠĠĠ Ġpreferences Ġ= ĠPreference Repository . getInstance ( context ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠSee Ġhttps :// developer . android . com / training / swipe / add - swipe - interface ĊĠĠĠ Ġprivate Ġfun Ġupdate Media List ( from Menu : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠSignal ĠSw ipe Refresh Layout Ġto Ġstart Ġthe Ġprogress Ġindicator ĊĠĠĠĠĠĠĠ Ġ// ĠNOTE : Ġrequired Ġonly Ġwhen Ġcalled Ġexplicitly , Ġe . g . Ġfrom Ġa Ġmenu Ġitem ĊĠĠĠĠĠĠĠ Ġif Ġ( from Menu ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . swipe Refresh . is Refresh ing Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠ Ġview Lifecycle Owner . lifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlist Adapter . refresh () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġactivity ?. run On Ui Thread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . swipe Refresh . is Refresh ing Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ////////////////////////////////////////////////////////////////// //////////////////////// ////// ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate ( savedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onCreate ( savedInstanceState ) ĊĠĠĠĠĠĠĠ Ġset Has Options Menu ( true ) ĊĊĠĠĠĠĠĠĠ Ġarguments ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . take If Ġ{ Ġ! it . isEmpty Ġ} ?. let Ġ{ Ġbundle Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilter Options Ġ= Ġbundle . get Parcelable < Media Filter >( ARG _ FILTER ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsort Options Ġ= Ġbundle . get Parcelable < Media Sort Arg >( ARG _ SORT ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġargs Constructor Ġ= ĠMedia List Fragment Args ( filter Options , Ġsort Options ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠTrigger Ġdatabase Ġcreation Ġand Ġinitialization Ġby Ġdoing Ġsome Ġquery ĊĠĠĠĠĠĠĠ Ġinitialize Database () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate View ( in flater : ĠLayoutInflater , Ġcontainer : ĠViewGroup ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠsavedInstanceState : ĠBundle ?): ĠView Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠInf late Ġthe Ġlayout Ġfor Ġthis Ġfragment ĊĠĠĠĠĠĠĠ Ġbinding Ġ= ĠFragment Media List Binding . inflate ( in flater , Ġcontainer , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġreturn Ġbinding . root ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon View Created ( view : ĠView , ĠsavedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on View Created ( view , ĠsavedInstanceState ) ĊĊĠĠĠĠĠĠĠ Ġsetup RecyclerView () ĊĠĠĠĠĠĠĠ Ġsetup Swipe On Refresh () ĊĊĠĠĠĠĠĠĠ Ġinit Search () ĊĊĠĠĠĠĠĠĠ Ġbinding . retry Button . setOnClickListener Ġ{ Ġlist Adapter . retry () Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( preferences . is First Run ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsetup Default Filter Options () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsetup Default Sort Option () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠwaitFor Database Ready () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġargs Ġ= Ġif Ġ( arguments Ġ!= Ġnull Ġ&& Ġarguments ?. isEmpty Ġ== Ġfalse ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġargs Constructor ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġargs Navigation ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilter Options Ġ= Ġargs . filter Options Ġ?: Ġpreferences . filter Options ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsort Option Ġ= Ġargs . sort Option ?. value Ġ?: Ġpreferences . sort Option ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsearch ( filter Options , Ġsort Option ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate Options Menu ( menu : ĠMenu , Ġinflater : ĠMenu Inflater ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠInf late Ġthe Ġmenu ; Ġthis Ġadds Ġitems Ġto Ġthe Ġaction Ġbar Ġif Ġit Ġis Ġpresent . ĊĠĠĠĠĠĠĠ Ġinflater . inflate ( R . menu . menu _ main , Ġmenu ) ĊĊĠĠĠĠĠĠĠ Ġsuper . onCreate Options Menu ( menu , Ġinflater ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠThis Ġhook Ġis Ġcalled Ġwhenever Ġan Ġitem Ġin Ġyour Ġoptions Ġmenu Ġis Ġselected ĊĠĠĠ Ġoverride Ġfun Ġon Options ItemSelected ( item : ĠMenuItem ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠHandle Ġaction Ġbar Ġitem Ġclicks Ġhere . ĠThe Ġaction Ġbar Ġwill ĊĠĠĠĠĠĠĠ Ġ// Ġautomatically Ġhandle Ġclicks Ġon Ġthe ĠHome / Up Ġbutton , Ġso Ġlong ĊĠĠĠĠĠĠĠ Ġ// Ġas Ġyou Ġspecify Ġa Ġparent Ġactivity Ġin ĠAndroid Manifest . xml . ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( item . itemId ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġhttps :// developer . android . com / training / swipe / respond - refresh - request ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ refresh Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Refresh Ġmenu Ġitem Ġselected ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠStart Ġthe Ġrefresh Ġbackground Ġtask . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġmethod Ġcalls Ġ` set Refresh ing ( false )` Ġwhen Ġit 's Ġfinished ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Media List ( true ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ settings Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġsuper . on Options ItemSelected ( item ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ////////////////////////////////////////////////////////////////// //////////////////////// ////// ĊĊĠĠĠ Ġprivate Ġfun Ġsetup RecyclerView () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠAdd Ġdiv iders Ġbetween ĠRecyclerView 's Ġrow Ġitems ĊĠĠĠĠĠĠĠ Ġval Ġdecoration Ġ= ĠDiv ider Item Decoration ( require Context (), ĠDiv ider Item Decoration . VERTICAL ) ĊĊĠĠĠĠĠĠĠ Ġval Ġheader Ġ= ĠMedia List Load State Adapter ( list Adapter ) ĊĊĠĠĠĠĠĠĠ Ġwith Ġ( binding . list ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . adapter Ġ= Ġlist Adapter . with Load State Header And Footer ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġheader Ġ= Ġheader , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfooter Ġ= ĠMedia List Load State Adapter ( list Adapter ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . addItem Decoration ( decoration ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlist Adapter . add Load State Listener Ġ{ Ġload State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠisLoading Ġ= Ġload State . medi ator ?. refresh Ġis ĠLoad State . Loading ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Refresh Suc ceeds Ġ= Ġload State . source . refresh Ġis ĠLoad State . Not Loading Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload State . medi ator ?. refresh Ġis ĠLoad State . Not Loading ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! isLoading Ġ&& Ġis Refresh Suc ceeds Ġ&& Ġ( list Adapter . item Count Ġ!= ĠNET WORK _ PAGE _ SIZE )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Data Loaded ?. invoke ( list Adapter . item Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlist Adapter . add Load State Listener Ġ{ Ġload State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Refresh Suc ceeds Ġ= Ġload State . source . refresh Ġis ĠLoad State . Not Loading Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload State . medi ator ?. refresh Ġis ĠLoad State . Not Loading ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġempty Ġlist ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis List Empty Ġ= Ġload State . refresh Ġis ĠLoad State . Not Loading Ġ&& Ġlist Adapter . item Count Ġ== Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshow Empty List ( is List Empty ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġa Ġretry Ġheader Ġif Ġthere Ġwas Ġan Ġerror Ġrefresh ing , Ġand Ġitems Ġwere Ġpreviously ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcached ĠOR Ġdefault Ġto Ġthe Ġdefault Ġprepend Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheader . load State Ġ= Ġload State . medi ator ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . refresh ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . take If Ġ{ Ġit Ġis ĠLoad State . Error Ġ&& Ġlist Adapter . item Count Ġ> Ġ 0 Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġload State . prepend ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOnly Ġshow Ġthe Ġlist Ġif Ġrefresh Ġsucceeds , Ġeither Ġfrom Ġthe Ġthe Ġlocal Ġdb Ġor Ġthe Ġremote ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . list . isVisible Ġ= Ġis Refresh Suc ceeds ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġloading Ġspinner Ġduring Ġinitial Ġload Ġor Ġrefresh ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . progress Bar . isVisible Ġ= Ġload State . medi ator ?. refresh Ġis ĠLoad State . Loading ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* binding . swipe Refresh . is Refresh ing Ġ= Ġload State . medi ator ?. refresh Ġis ĠLoad State . Loading */ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġthe Ġretry Ġstate Ġif Ġinitial Ġload Ġor Ġrefresh Ġfails Ġand Ġthere Ġare Ġno Ġitems ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . retry Button . isVisible Ġ= Ġload State . medi ator ?. refresh Ġis ĠLoad State . Error Ġ&& Ġlist Adapter . item Count Ġ== Ġ 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠToast Ġon Ġany Ġerror , Ġregardless Ġof Ġwhether Ġit Ġcame Ġfrom ĠRemote Mediator Ġor ĠP aging Source ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġerror State Ġ= Ġload State . source . append Ġas ? ĠLoad State . Error ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġload State . source . prepend Ġas ? ĠLoad State . Error ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġload State . append Ġas ? ĠLoad State . Error ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġload State . prepend Ġas ? ĠLoad State . Error ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerror State ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠToast . makeText ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequire Context (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ uD 8 3 D \ u DE 2 8 ĠW oo ops Ġ${ it . error }", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠToast . LENGTH _ LONG ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ). show () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinit Search () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠNOTE : Ġthis Ġbehaviour Ġlooks Ġlike Ġunnecessary ĊĠĠĠĠĠĠĠ Ġ// ĠScroll Ġto Ġtop Ġwhen Ġthe Ġlist Ġis Ġref reshed Ġfrom Ġnetwork ĊĠĠĠĠĠĠĠ Ġ/* view Lifecycle Owner . lifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlist Adapter . load State Flow ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOnly Ġemit Ġwhen ĠREF RESH ĠLoad State Ġfor ĠRemote Mediator Ġchanges ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. distinct Until Changed By Ġ{ Ġit . refresh Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOnly Ġreact Ġto Ġcases Ġwhere ĠRemote Ġ` REFRESH ` Ġcompletes Ġi . e ., Ġ` Not Loading ` ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . refresh Ġis ĠLoad State . Not Loading Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. collect Ġ{ Ġbinding . list . scrollTo Position ( 0 ) Ġ} ĊĠĠĠĠĠĠĠ Ġ}*/ ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġhttps :// developer . android . com / training / swipe / respond - refresh - request ĊĠĠĠ Ġprivate Ġfun Ġsetup Swipe On Refresh () Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Ġ( binding . swipe Refresh ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSets Ġup Ġa ĠSw ipe Refresh Layout . On Refresh Listener Ġthat Ġis Ġinvoked ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwhen Ġthe Ġuser Ġperforms Ġa Ġswipe - to - refresh Ġgesture . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . setOn Refresh Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" on Refresh Ġcalled Ġfrom ĠSw ipe Refresh Layout ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġmethod Ġperforms Ġthe Ġactual Ġdata - refresh Ġoperation . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġmethod Ġcalls Ġ` set Refresh ing ( false )` Ġwhen Ġit 's Ġfinished ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Media List ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/* fun Ġscroll Up () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// list Adapter . retry () ĊĠĠĠĠĠĠĠ Ġbinding . list . scrollTo Position ( 0 ) ĊĠĠĠ Ġ}*/ ĊĊĠĠĠ Ġfun Ġsearch ( filter : ĠMedia Filter , ĠsortBy : ĠMedia Sort ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠMake Ġsure Ġwe Ġcancel Ġthe Ġprevious Ġjob Ġbefore Ġcreating Ġa Ġnew Ġone ĊĠĠĠĠĠĠĠ Ġsearch Job ?. cancel () ĊĊĠĠĠĠĠĠĠ Ġ// ĠOb serve Ġmedia Ġlist Ġloading ĊĠĠĠĠĠĠĠ Ġsearch Job Ġ= Ġview Lifecycle Owner . lifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . get Media List Stream ( filter , ĠsortBy ). collect Latest Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlist Adapter . submit Data ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Empty List ( show : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( show ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . emptyList . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . list . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . emptyList . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . list . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠThis Ġcall Ġ" to uches " Ġthe Ġdatabase Ġand Ġcause Ġits Ġworker Ġto Ġstart ĊĠĠĠ Ġprivate Ġfun Ġinitialize Database () Ġ{ ĊĠĠĠĠĠĠĠ Ġlifecycle Scope . launch When Created Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdao Ġ= ĠMedia Database . getInstance ( require Context ()). media Dao () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmedia Count Ġ= Ġdao . getAll Media Count () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Got Ġ$ media Count Ġmedia Ġfrom Ġdatabase ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Default Filter Options () Ġ{ ĊĠĠĠĠĠĠĠ Ġpreferences . filter Options Ġ= ĠMedia Filter ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġyear Ġ= ĠLocalDate . now (). year , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstatus Ġ= ĠMedia Status . RE LE AS ING , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġformats Ġ= ĠlistOf ( Media Format Enum . TV ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Default Sort Option () Ġ{ ĊĠĠĠĠĠĠĠ Ġpreferences . sort Option Ġ= ĠMedia Sort . BY _ POP ULAR ITY ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠwaitFor Database Ready () Ġ{ ĊĠĠĠĠĠĠĠ ĠWork Manager . getInstance ( require Context ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. get Work Infos By Tag LiveData ( INIT _ DATABASE _ WORK ER _ TAG ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe ( view Lifecycle Owner , Ġ{ Ġwork InfoList : ĠList < Work Info > Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( work InfoList . isEmpty ()) Ġreturn @ observe ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġwork Info Ġ= Ġwork InfoList . first () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( work Info . state ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠWork Info . State . SUCCEEDED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Init Ġdatabase Ġworker Ġstate Ġchanged Ġto Ġ' SUCCEEDED '") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠMark Ġthe Ġfirst Ġrun Ġproperty Ġas Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpreferences . is First Run Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġthe Ġmedia Ġlist ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsearch ( preferences . filter Options , Ġpreferences . sort Option ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Init Ġdatabase Ġworker Ġstate Ġchanged Ġto Ġ'${ work Info . state . name }' ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : Ġdo Ġsomething Ġwith Ġprogress Ġinformation ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// val Ġvalue Ġ= Ġwork Info . progress . getInt ( INIT _ DATABASE _ WORK ER _ PROGRESS _ KEY , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ////////////////////////////////////////////////////////////////// //////////////////////// ////// ĊĊĠĠĠ Ġ/* comp anion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġfun Ġnew Instance ( filter : ĠMedia Filter , Ġsort : ĠMedia Sort ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMedia List Fragment (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġarguments Ġ= ĠBundle (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Parcelable ( ARG _ FILTER , Ġfilter ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Parcelable ( ARG _ SORT , ĠMedia Sort Arg ( sort )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}*/ Ċ } Ċ