package Ġcom . github . mr bean 3 5 5 . android Ċ Ċ import Ġandroidx . annotation . Visible ForTesting Ċ import Ġandroidx . collection . Array Set Ċ import Ġandroidx . recyclerview . widget . Diff Util Ċ import Ġandroidx . recyclerview . widget . RecyclerView Ċ import Ġjava . util . Queue Ċ import Ġjava . util . concurrent . Concurrent Linked Queue Ċ Ċ abstract Ġclass ĠEn hanced Adapter < T , ĠV H Ġ: ĠRecyclerView . ViewHolder >( ĊĠĠĠ Ġprivate Ġval Ġdiff Callback : ĠDiff Util . Item Callback < T >, ĊĠĠĠ Ġprivate Ġval Ġmax Selections : ĠInt Ċ ) Ġ: ĠRecyclerView . Adapter < VH >() Ġ{ ĊĊĠĠĠ Ġ/** ĠFull Ġlist Ġof Ġthe Ġmaintained Ġitems . Ġ*/ ĊĠĠĠ Ġ@ Visible ForTesting ĊĠĠĠ Ġinternal Ġvar Ġsource Items : ĠList < T > Ġ= Ġempty List () ĊĊĠĠĠ Ġ/** ĠItems Ġthat Ġare Ġcurrently Ġbeing Ġdisplayed . Ġ*/ ĊĠĠĠ Ġ@ Visible ForTesting ĊĠĠĠ Ġinternal Ġvar Ġdisplayed Items : ĠList < T > Ġ= Ġempty List () ĊĊĠĠĠ Ġ/** ĠItems Ġthat Ġare Ġcurrently Ġselected . Ġ*/ ĊĠĠĠ Ġ@ Visible ForTesting ĊĠĠĠ Ġinternal Ġval Ġselected Items : ĠMutable Set < T > Ġ= Ġmutable Set Of () ĊĊĠĠĠ Ġ/** ĠPending Ġlist Ġupdates . Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġupdate Queue : ĠQueue < List < T >> Ġ= ĠConcurrent Linked Queue () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠOverride Ġto Ġcustom ise Ġitem Ġsorting . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠPerforms Ġno Ġsorting Ġby Ġdefault . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġopen Ġfun Ġcompare Items ( lhs : ĠT , Ġrhs : ĠT ): ĠInt Ġ= Ġ 0 ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠOverride Ġto Ġimplement Ġitem Ġfiltering . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠCalling Ġ[ filter ] Ġwithout Ġproviding Ġcustom Ġbehaviour Ġhere Ġwill Ġcause Ġno Ġitems Ġto Ġbe Ġdisplayed . ĊĠĠĠĠ Ġ* Ġ[ query ] Ġwill Ġnever Ġbe Ġempty . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġopen Ġfun Ġtest Item ( item : ĠT , Ġquery : ĠString ): ĠBoolean Ġ= Ġfalse ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSet Ġthe Ġadapter 's Ġitems . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ[ compare Items ] Ġwill Ġbe Ġused Ġto Ġcompare Ġitems . ĊĠĠĠĠ Ġ* ĠRe sets Ġany Ġfiltering Ġdone Ġvia Ġ[ filter ]. ĊĠĠĠĠ Ġ* ĠI g no res Ġany Ġ` null ` Ġelements Ġin Ġthe Ġcollection . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġset Items ( items : ĠCollection < T > ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . source Items Ġ= Ġitems . or Empty (). sorted With Ġ{ Ġo 1 , Ġo 2 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcompare Items ( o 1 , Ġo 2 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġpublish List ( source Items ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ return Ġa Ġset Ġof Ġcurrently Ġselected Ġitems . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Selected Items (): ĠSet < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠArray Set ( selected Items ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSet Ġthe Ġcurrently Ġselected Ġitems . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun ĠsetSelected Items ( selection : ĠCollection < T >) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( selection . size Ġ> Ġmax Selections ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Tri ed Ġto Ġselect Ġmore Ġitems Ġ(${ selection . size }) Ġthan Ġmax Ġ($ max Selections )") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġchanged Items Ġ= Ġdis j unct ive Union ( selected Items , Ġselection ) ĊĠĠĠĠĠĠĠ Ġselected Items . clear () ĊĠĠĠĠĠĠĠ Ġselected Items . addAll ( selection ) ĊĠĠĠĠĠĠĠ Ġchanged Items . map Ġ{ Ġdisplayed Items . indexOf ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit Ġ!= Ġ- 1 Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġnotify Item Changed ( it ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠFilter Ġthe Ġdisplayed Ġitems Ġbased Ġon Ġsome Ġ[ query ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠA Ġ` null ` Ġor Ġempty Ġ[ query ] Ġcauses Ġall Ġitems Ġto Ġbe Ġdisplayed . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġfilter ( query : ĠString ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( query . isNull OrEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpublish List ( source Items ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġfiltered Ġ= Ġthis . source Items . filter Ġ{ Ġtest Item ( it , Ġquery ) Ġ} ĊĠĠĠĠĠĠĠ Ġpublish List ( filtered ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ return Ġ` true ` Ġif Ġthe Ġdisplayed Ġitem Ġat Ġ[ position ] Ġis Ġcurrently Ġselected , Ġ` false ` Ġotherwise . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġis ItemSelected ( position : ĠInt ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġselected Items . contains ( getItem At ( position )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetItem Count () Ġ= Ġdisplayed Items . size ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġcurrently Ġdisplayed Ġitem Ġat Ġ[ position ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġfun ĠgetItem At ( position : ĠInt ) Ġ= Ġdisplayed Items [ position ] ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTrigger Ġa Ġselection Ġevent ; Ġselecting Ġthe Ġitem Ġat Ġ[ adapter Position ] Ġif Ġits Ġnot Ġselected , Ġand Ġde select ing Ġit Ġotherwise . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġfun Ġon Item Clicked ( adapter Position : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġitem Ġ= ĠgetItem At ( adapter Position ) ĊĠĠĠĠĠĠĠ Ġif Ġ( selected Items . contains ( item )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġselected Items . remove ( item ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Item Changed ( adapter Position ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( selected Items . size Ġ< Ġmax Selections ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġselected Items . add ( item ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Item Changed ( adapter Position ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠUpdate Ġthe Ġdisplayed Ġlist , Ġdoing Ġdiff Ġcalculations Ġin Ġthe Ġbackground . Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġpublish List ( update : ĠList < T >) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate Queue . add ( ArrayList ( update )) ĊĠĠĠĠĠĠĠ Ġif Ġ( update Queue . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNo Ġother Ġupdates Ġin Ġprogress ; Ġprocess Ġthis Ġupdate . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Queue () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠProcess Ġthe Ġnext Ġupdate Ġin Ġthe Ġ[ update Queue ]. Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġprocess Queue () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnew List Ġ= Ġupdate Queue . element () ĊĠĠĠĠĠĠĠ ĠEn hanced Adapter Executors Impl . execute On Worker Thread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= ĠDiff Util . calculate Diff ( Diff Callback ( display ed Items , Ġnew List , Ġdiff Callback )) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠEn hanced Adapter Executors Impl . execute On MainThread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . display ed Items Ġ= Ġnew List ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . dispatch Updates To ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Queue . remove () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( update Queue . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Queue () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġcompanion Ġobject Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ/** ĠReturn Ġa Ġcollection Ġof Ġitems Ġthat Ġare Ġin Ġeither Ġ[ a ] Ġor Ġ[ b ], Ġbut Ġnot Ġboth . Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġ< T > Ġdis j unct ive Union ( a : ĠCollection < T >, Ġb : ĠCollection < T >): ĠCollection < T > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġa . union ( b ). to Mutable Set () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintersect Ġ= Ġa . intersect ( b ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . removeAll ( intersect ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** Ġ[ Diff Util . Callback ] Ġwhich Ġdeleg ates Ġitem Ġchecks Ġto Ġanother Ġ[ callback ]. Ġ*/ ĊĠĠĠ Ġprivate Ġclass ĠDiff Callback < T >( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġold List : ĠList < T >, ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġnew List : ĠList < T >, ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcallback : ĠDiff Util . Item Callback < T > ĊĠĠĠ Ġ) Ġ: ĠDiff Util . Callback () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġget Old List Size () Ġ= Ġold List . size ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġget New List Size () Ġ= Ġnew List . size ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġare Items The Same ( old Item Position : ĠInt , Ġnew Item Position : ĠInt ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcallback . are Items The Same ( old List [ old Item Position ], Ġnew List [ new Item Position ]) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġare Contents The Same ( old Item Position : ĠInt , Ġnew Item Position : ĠInt ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcallback . are Contents The Same ( old List [ old Item Position ], Ġnew List [ new Item Position ]) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }