/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠS ank et ĠB hat Ċ Ġ* Ċ Ġ* ĠĠĠ Ġ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 Ġcom . ud acity . s ank et b hat . popular movies . ui Ċ Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . view . LayoutInflater Ċ import Ġandroid . view . MenuItem Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroidx . databinding . Data Binding Util Ċ import Ġandroidx . fragment . app . Fragment Ċ import Ġandroidx . lifecycle . ViewModel Provider Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġandroidx . paging . Load State Ċ import Ġandroidx . paging . Paging Data Ċ import Ġandroidx . recyclerview . widget . Concat Adapter Ċ import Ġandroidx . recyclerview . widget . RecyclerView Ċ import Ġcom . ud acity . s ank et b hat . popular movies . R Ċ import Ġcom . ud acity . s ank et b hat . popular movies . adapter . Movie ClickListener Ċ import Ġcom . ud acity . s ank et b hat . popular movies . adapter . Movie Grid LayoutManager Ċ import Ġcom . ud acity . s ank et b hat . popular movies . adapter . Movie ListAdapter Ċ import Ġcom . ud acity . s ank et b hat . popular movies . adapter . Movie Load State Adapter Ċ import Ġcom . ud acity . s ank et b hat . popular movies . databinding . Activity Movie List Fragment Binding Ċ import Ġcom . ud acity . s ank et b hat . popular movies . model . SortOrder Ċ import Ġcom . ud acity . s ank et b hat . popular movies . util . Preference Utils . get Preferred SortOrder Ċ import Ġkotlinx . coroutines . Job Ċ import Ġkotlinx . coroutines . flow . collect Ċ import Ġkotlinx . coroutines . flow . collect Latest Ċ import Ġkotlinx . coroutines . flow . distinct Until Changed By Ċ import Ġkotlinx . coroutines . flow . filter Ċ import Ġkotlinx . coroutines . launch Ċ Ċ class ĠMovie List Fragment Ġ: ĠFragment () Ġ{ ĊĠĠĠ Ġprivate Ġlateinit Ġvar ĠviewModel : ĠMovie List ViewModel ĊĠĠĠ Ġprivate Ġvar Ġm Binding : ĠActivity Movie List Fragment Binding ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġgrid LayoutManager : ĠMovie Grid LayoutManager ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġadapter : ĠMovie ListAdapter ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġmovie Request Job : ĠJob ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate ( savedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onCreate ( savedInstanceState ) ĊĠĠĠĠĠĠĠ ĠviewModel Ġ= ĠViewModel Provider ( this ). get ( Movie List ViewModel :: class . java ) ĊĠĠĠĠĠĠĠ Ġset Has Options Menu ( true ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate View ( in flater : ĠLayoutInflater , Ġcontainer : ĠViewGroup ?, ĠsavedInstanceState : ĠBundle ?): ĠView ? Ġ{ ĊĠĠĠĠĠĠĠ Ġset Activity Title () ĊĠĠĠĠĠĠĠ Ġval Ġroot View Ġ= Ġinflater . inflate ( R . layout . activity _ movie _ list _ fragment , Ġcontainer , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġm Binding Ġ= ĠData Binding Util . bind ( root View ) ĊĠĠĠĠĠĠĠ Ġm Binding ?. let Ġ{ Ġm Binding Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshow Movie List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsetup RecyclerView ( m Binding . movie List ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġm Binding . movie List Error Retry Button . setOnClickListener Ġ{ Ġadapter ?. refresh () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest For Movies () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġroot View ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġset Activity Title () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( activity Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( get Preferred SortOrder ( activity !!. application Context )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSort Order . SORT _ ORDER _ POP ULAR Ġ-> Ġactivity !!. title Ġ= ĠgetString ( R . string . title _ popular _ movie ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSort Order . SORT _ ORDER _ TOP _ R ATED Ġ-> Ġactivity !!. title Ġ= ĠgetString ( R . string . title _ top _ r ated _ movie ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġactivity !!. setTitle ( R . string . app _ name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrequest For Movies () Ġ{ ĊĠĠĠĠĠĠĠ Ġmovie Request Job ?. cancel () ĊĠĠĠĠĠĠĠ Ġmovie Request Job Ġ= Ġlifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . get Paged Movies ( get Preferred SortOrder ( context )). collect Latest Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadapter ?. submit Data ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Options ItemSelected ( item : ĠMenuItem ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( item . itemId ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . menu _ sort _ pop ularity , ĠR . id . menu _ sort _ rating Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadapter ?. submit Data ( lifecycle , ĠP aging Data . empty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest For Movies () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Activity Title () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġsuper . on Options ItemSelected ( item ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup RecyclerView ( re cyclerView : ĠRecyclerView ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Initialize Ġadapter Ġwith Ġnull Ġmovie Ġitems . ĠBecause Ġit Ġwill Ġbe Ġset Ġonce Ġit Ġis Ġavailable ĊĠĠĠĠĠĠĠ Ġadapter Ġ= ĠMovie ListAdapter ( context !! , Ġactivity Ġas ĠMovie ClickListener ?) ĊĊĠĠĠĠĠĠĠ Ġadapter ?. add Load State Listener Ġ{ Ġload State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( load State . source . refresh ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠLoad State . Not Loading Ġ-> Ġshow Movie List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠLoad State . Loading Ġ-> Ġshow Movie Loading () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠLoad State . Error Ġ-> Ġshow Error Layout () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġlifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ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 ĠREF RESH Ġcompletes Ġi . e ., ĠNot Loading . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . filter Ġ{ Ġit . refresh Ġis ĠLoad State . Not Loading Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . collect Ġ{ Ġm Binding ?. movie List ?. scrollTo Position ( 0 ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġfooter Adapter Ġ= ĠMovie Load State Adapter { adapter ?. retry ()} ĊĠĠĠĠĠĠĠ Ġadapter ?. add Load State Listener Ġ{ Ġload State Ġ-> Ġfooter Adapter . load State Ġ= Ġload State . append Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġconcat Adapter Ġ= ĠConcat Adapter ( Concat Adapter . Config . Builder (). setIs olate View Types ( false ). build (), adapter , Ġfooter Adapter ); ĊĠĠĠĠĠĠĠ Ġre cyclerView . adapter Ġ= Ġconcat Adapter ĊĠĠĠĠĠĠĠ Ġgrid LayoutManager Ġ= ĠMovie Grid LayoutManager ( context !! , Ġre cyclerView . adapter !! ) ĊĠĠĠĠĠĠĠ Ġre cyclerView . layout Manager Ġ= Ġgrid LayoutManager ĊĠĠĠĠĠĠĠ Ġre cyclerView . set Has Fixed Size ( true ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Helper Ġmethods Ġfor Ġshowing Ġthree Ġdifferent Ġlayouts Ġlist , Ġloading , Ġerror . ĊĠĠĠ Ġprivate Ġfun Ġshow Movie List () Ġ{ ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List ?. visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie Load Progress ?. visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List Error Layout ?. visibility Ġ= ĠView . GONE ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Movie Loading () Ġ{ ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List ?. visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie Load Progress ?. visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List Error Layout ?. visibility Ġ= ĠView . GONE ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Error Layout () Ġ{ ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List ?. visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie Load Progress ?. visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġm Binding ?. movie List Error Layout ?. visibility Ġ= ĠView . VISIBLE ĊĠĠĠ Ġ} Ċ }