package Ġen chant . magic Ċ Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . flow . Mutable State Flow Ċ import Ġkotlinx . coroutines . flow . launch In Ċ import Ġkotlinx . coroutines . flow . on Each Ċ Ċ /** Ċ Ġ* ĠA Ġmore Ġadvanced Ġversion Ġof Ġ[ ViewModel ] Ġthat Ġintegr ates Ġ[ Status ] Ġto Ġrepresent Ġthe Ġprogress Ġof Ċ Ġ* Ġcertain Ġoperations : Ċ Ġ* Ċ Ġ* Ġ- ĠThe Ġprocess Ġof Ġcreating Ġstates Ġof Ġtype Ġ[ Status ] Ġis Ġautomated Ġthrough Ġthe Ġstatus Ġmap , Ġwhich Ċ Ġ* Ġbundles Ġall Ġstatus Ġstates Ġtogether . ĠKeys Ġof Ġa Ġcustom Ġ( enum ) Ġtype Ġ[ T ] Ġrepresent Ġthe Ġkeys Ġwhich Ġcan Ċ Ġ* Ġbe Ġused Ġto Ġ[ get ] Ġthe Ġvalues Ġof Ġstatus Ġstates . Ċ Ġ* Ċ Ġ* Ġ- ĠThe Ġ[ status ] Ġand Ġ[ single Status ] Ġbuild ers Ġare Ġable Ġto Ġtrack Ġthe Ġprogress Ġof Ġrunning Ġcode Ġand Ċ Ġ* Ġoutput Ġto Ġa Ġgiven Ġstatus Ġstate . ĠThis Ġallows Ġfor Ġautomatic Ġerror Ġhandling , Ġassuming Ġthat Ġfunctions Ċ Ġ* Ġfrom ĠMV VM Ġmodels Ġthrow Ġerrors . ĠThese Ġerrors Ġare Ġcaught Ġand Ġconverted Ġto Ġthe Ġ[ Issue ] Ġtype Ġvia Ċ Ġ* Ġ[ map Result ], Ġwhich Ġcan Ġbe Ġover loaded Ġto Ġadd Ġconversion Ġto Ġ[ Status . code ]. Ċ Ġ* Ċ Ġ* Ġ- ĠIncludes Ġstatus Ġstates Ġwithin Ġthe Ġstatus Ġmap Ġin Ġ[ ViewModel . toString ] Ġand Ġ[ ViewModel . print Changes ] Ċ Ġ*/ Ċ open Ġclass ĠStatus ViewModel < T >( debug : ĠBoolean Ġ= Ġfalse ) Ġ: ĠViewModel ( debug ) Ġ{ ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġthe Ġassociated Ġ[ Status ] Ġvalue Ġfor Ġthe Ġ[ k ]. ĠIf Ġthe Ġstatus Ġstate Ġat Ġthe Ġcurrent Ġkey ĊĠĠĠĠ Ġ* Ġhas Ġnot Ġbeen Ġset Ġyet , Ġ[ Not Started ] Ġis Ġreturned ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġk ĠThe Ġunique Ġstatus Ġkey / identifier Ġthat Ġidentifies Ġthe Ġstatus Ġstate Ġto Ġaccess ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun Ġget ( k : ĠT ): ĠStatus Ġ= Ġstatuses [ k ] ĊĊĠĠĠ Ġprotected Ġval Ġstatuses Ġ= ĠStatus Map (:: refresh ) ĊĊĠĠĠ Ġprotected Ġinner Ġclass ĠStatus Map ( val Ġrefresh : Ġ() Ġ-> ĠUnit ) Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġmap Ġ= Ġhash Map Of < T , ĠStatus >() ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġstate Scope Ġ= ĠCor outine Scope ( coroutine Context Ġ+ ĠJob ()) ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġstates : ĠMap < T , ĠMutable State Flow < Status >> Ġ= Ġmap Of () ĊĊĠĠĠĠĠĠĠ Ġfun ĠsetState Flows ( states : ĠMap < T , ĠMutable State Flow < Status >>) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Scope . cancel () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Scope Ġ= ĠCor outine Scope ( coroutine Context Ġ+ ĠJob ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstates . forEach Ġ{ Ġentry Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . value . on Each Ġ{ Ġset ( entry . key , Ġit ) Ġ}. launch In ( state Scope ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoperator Ġfun Ġget ( key : ĠT ): ĠStatus Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstates [ key ]?. value Ġ?: Ġmap . get Or Put ( key ) Ġ{ ĠNot Started () Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠRe sets Ġall Ġ[ Status ] Ġvalues Ġto ĠNot Started Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġreset () Ġ= Ġmap . clear () ĊĊĠĠĠĠĠĠĠ Ġ/** ĠUpdates Ġthe Ġvalue Ġof Ġthe Ġstatus Ġstate Ġat Ġthe Ġgiven Ġ[ key ] Ġand Ġref res hes Ġthe ĠViewModel Ġ*/ ĊĠĠĠĠĠĠĠ Ġoperator Ġfun Ġset ( key : ĠT , Ġvalue : ĠStatus ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠoldValue Ġ= Ġget ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key Ġin Ġstates ) Ġstates [ key ] !!. value Ġ= Ġvalue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġmap [ key ] Ġ= Ġvalue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( print Changes ) Ġprintln ("$ object Label : Ġ[$ key ] Ġ= Ġ$ value ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( value Ġ!= ĠoldValue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key Ġin Ġ_ blocked Statuses ) Ġ_ commit Changes Ġ= Ġtrue Ġelse Ġrefresh () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠtoString (): ĠString Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap . toList (). sorted By Ġ{ Ġit . first . toString () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString ("\ n ") Ġ{ Ġ"[ ${ it . first }] Ġ= Ġ${ it . second }" Ġ} ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĠAfter Ġthe Ġ[ status ] Ġor Ġ[ single Status ] Ġbuilder Ġfinishes Ġrunning Ġits Ġcontained Ġcode , Ġ[ map Result ] ĊĠĠĠĠ Ġ* Ġis Ġcalled Ġwith Ġthe Ġcode 's Ġ[ result ]. ĠThe Ġ[ result ] Ġwill Ġbe Ġ[ Result . success ] Ġif Ġthe Ġcode Ġfinished ĊĠĠĠĠ Ġ* Ġexecuting Ġcompletely . ĠOtherwise , Ġthe Ġ[ result ] Ġwill Ġbe Ġ[ Result . failure ], Ġincluding Ġthe ĊĠĠĠĠ Ġ* Ġ[ Throwable ] Ġthrown Ġby Ġthe Ġcode . ĠAfter Ġ[ map Result ] Ġreturns Ġthe Ġ[ Status ] Ġconverted Ġfrom Ġ[ Result ], ĊĠĠĠĠ Ġ* Ġthe Ġstatus Ġstate Ġwithin Ġthe Ġstatus Ġbuilder Ġwill Ġbe Ġset Ġto Ġthe Ġreturned Ġstatus . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġfunction Ġshould Ġbe Ġoverridden Ġto Ġadd Ġcustom Ġerror Ġcode Ġbehavior , Ġso Ġthat Ġthe ĠUI Ġcan ĊĠĠĠĠ Ġ* Ġunderstand Ġthe Ġissue Ġthrown Ġby Ġthe Ġcode . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġopen Ġfun Ġmap Result ( result : ĠResult < Unit >): ĠStatus Ġ= ĊĠĠĠĠĠĠĠ Ġif Ġ( result . is Success ) ĠSuccess () Ġelse ĠIssue () ĊĊĠĠĠ Ġ/** ĠThe Ġstatus Ġbuilder Ġmonitor s Ġthe Ġprogress Ġof Ġthe Ġgiven Ġ[ action ] Ġcode Ġand Ġoutputs Ġit Ġto Ġthe ĊĠĠĠĠ Ġ* Ġstatus Ġstate Ġat Ġthe Ġprovided Ġ[ key ]. ĠThe Ġstatus Ġstate Ġwill Ġautomatically Ġupdate Ġbased Ġupon Ġthe ĊĠĠĠĠ Ġ* Ġcode Ġthat Ġis Ġrunning Ġinside Ġof Ġit : ĊĠĠĠĠ Ġ* Ġ- ĠWhen Ġthe Ġcode Ġis Ġrunning , Ġthe Ġstatus Ġis Ġset Ġto Ġ[ Loading ] ĊĠĠĠĠ Ġ* Ġ- ĠWhen Ġthe Ġcode Ġcompletes Ġsuccessfully , Ġthe Ġstatus Ġis Ġset Ġto Ġ[ Success ] ĊĠĠĠĠ Ġ* Ġ- ĠWhen Ġthe Ġcode Ġthrows Ġa Ġsystem Ġerror , Ġthe Ġerror Ġis Ġsent Ġto Ġ[ map Result ] Ġand Ġconverted Ġto Ġ[ Issue ] ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠNote : ĠWhen Ġthe Ġcode Ġthrows Ġan Ġerror , Ġthe Ġstatus Ġbuilder Ġstop Ġexecuting Ġthe Ġcode , Ġcancel Ġthe ĊĠĠĠĠ Ġ* Ġcoroutine Ġits Ġrunning Ġinside Ġof , Ġand Ġprevent Ġany Ġother Ġcode Ġin Ġthe Ġsame Ġcoroutine Ġfrom ĊĠĠĠĠ Ġ* Ġrunning . ĠThis Ġm im ics Ġthe Ġtraditional Ġ" throw Ġerror " Ġbehavior Ġbut Ġonly Ġaffects Ġthe Ġcurrent Ġcoroutine . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġkey ĠThe Ġunique Ġkey Ġof Ġthe Ġstatus Ġstate Ġyou Ġwant Ġto Ġchange ĊĠĠĠĠ Ġ* Ġ@ param Ġloading ĠIf Ġtrue , Ġsets Ġstatus Ġto Ġ[ Status . Loading ] Ġwhen Ġthe Ġcode Ġis Ġrunning . ĠMake ĊĠĠĠĠ Ġ* Ġfalse Ġfor Ġsuper Ġquick Ġ[ action ] s Ġwhere Ġloading ĠUI Ġisn 't Ġhelpful . ĊĠĠĠĠ Ġ* Ġ@ param Ġthrows ĠIf Ġtrue , Ġthe Ġstatus Ġwill Ġthrow Ġa Ġcoroutine Ġ[ Cancellation Exception ] Ġand Ġnot Ġexecute ĊĠĠĠĠ Ġ* Ġthe Ġcode Ġafter Ġif Ġthe Ġresulting Ġstatus Ġis Ġ[ Issue ]. ĠStatus Ġbuilder Ġmust Ġbe Ġrun Ġin Ġa Ġcoroutine . ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĠLambda Ġcontaining Ġthe Ġactual Ġcode Ġto Ġrun Ġand Ġmonitor . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġinline Ġfun Ġstatus ( ĊĠĠĠĠĠĠĠ Ġkey : ĠT , ĊĠĠĠĠĠĠĠ Ġloading : ĠBoolean Ġ= Ġtrue , ĊĠĠĠĠĠĠĠ Ġthrows : ĠBoolean Ġ= Ġtrue , ĊĠĠĠĠĠĠĠ Ġaction : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġ): ĠStatus Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( loading ) Ġstatuses [ key ] Ġ= ĠLoading () ĊĠĠĠĠĠĠĠ Ġval Ġaction Status : ĠStatus Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap Result ( Result . success ( action ())) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( t Ġis ĠIssue Exception ) Ġt . issue Ġelse Ġmap Result ( Result . failure ( t )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġstatuses [ key ] Ġ= Ġaction Status ĊĠĠĠĠĠĠĠ Ġif Ġ( action Status Ġis ĠIssue Ġ&& Ġthrows ) Ġthrow ĠC ancellation Exception (" status () Ġencountered Ġan Ġissue ") ĊĠĠĠĠĠĠĠ Ġreturn Ġaction Status ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠPre vents Ġmultiple Ġref res hes Ġfrom Ġhappening Ġwhen Ġwriting Ġto Ġmultiple Ġstates Ġand / or Ġstatuses . ĊĠĠĠĠ Ġ* ĠAfter Ġthe Ġcode Ġin Ġthe Ġ[ block ] Ġis Ġexecuted , Ġa Ġsingle Ġrefresh Ġwill Ġhappen Ġto Ġdisplay Ġthe Ġupdated ĊĠĠĠĠ Ġ* Ġchanges . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġstates ĠThe Ġnames Ġof Ġthe Ġstates Ġand Ġkeys Ġof Ġthe Ġstatuses Ġthat Ġwill Ġbe Ġexplicitly Ġblocked ĊĠĠĠĠ Ġ* Ġfrom Ġrefresh ing . ĠItems Ġmust Ġbe Ġa Ġ[ String ] Ġof Ġa Ġstate 's Ġname Ġor Ġa Ġ[ T ] Ġof Ġa Ġstatus ' Ġkey ĊĠĠĠĠ Ġ* Ġ@ param Ġblock ĠCode Ġthat Ġsets Ġthe Ġ[ states ] Ġand Ġ[ statuses ]. ĠIf Ġuser - input Ġstates Ġare Ġbeing Ġchanged , Ġit Ġis ĊĠĠĠĠ Ġ* Ġrecommended Ġthis Ġcode Ġexecutes Ġvery Ġquickly Ġwithout Ġlong Ġoperations Ġso Ġthat Ġthe Ġstate Ġdoes Ġnot ĊĠĠĠĠ Ġ* Ġappear Ġas Ġ" frozen ." ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġvar Ġ_ blocked Statuses : ĠMutable Set < T > Ġ= Ġmutable Set Of () ĊĊĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠ Ġprotected Ġinline Ġfun Ġcommit ( var arg Ġvalues : ĠAny , Ġblock : Ġ(() Ġ-> ĠUnit )) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstates : ĠArray Deque < String > Ġ= ĠArray Deque ( states . size ) ĊĠĠĠĠĠĠĠ Ġfor Ġ( state Ġin Ġvalues ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( state Ġis ĠString ) Ġstates Ġ+= Ġstate Ġelse Ġ_ blocked Statuses Ġ+= Ġstate Ġas ĠT ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġcommit ( states Ġ= Ġstates . to Typed Array (), Ġblock ) ĊĠĠĠĠĠĠĠ Ġ_ blocked Statuses Ġ= Ġmutable Set Of () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġ[ debug ] Ġmode Ġis Ġenabled , Ġthe Ġstring Ġoutput Ġwill Ġcontain Ġall Ġof Ġ[ Status ViewModel ]' s ĊĠĠĠĠ Ġ* Ġassociated Ġstates , Ġstatuses Ġand Ġseries . ĠOtherwise Ġthe Ġstring Ġoutput Ġwill Ġbe Ġthe Ġstandard ĊĠĠĠĠ Ġ* Ġobject Ġ[ toString ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠHere Ġis Ġa Ġsample Ġof Ġthe Ġ[ toString ] Ġoutput Ġin Ġ[ debug ] Ġmode : ĊĠĠĠĠ Ġ* Ġ``` ĊĠĠĠĠ Ġ* ĠStatus ViewModel @ 7 fb db 8 9 4 Ġstates Ġand Ġstatuses : ĊĠĠĠĠ Ġ* Ġname Ġ= ĠMichael ĊĠĠĠĠ Ġ* Ġage Ġ= Ġ 2 7 ĊĠĠĠĠ Ġ* Ġ[ Name Valid ] Ġ= ĠSuccess ĊĠĠĠĠ Ġ* Ġ[ Upload ] Ġ= ĠLoading ĊĠĠĠĠ Ġ* Ġ( ViewModel ) ĠDefault Series @ 1 1 9 cbf 9 6 Ġhas Ġno Ġrunning Ġtasks ĊĠĠĠĠ Ġ* Ġ``` ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun ĠtoString (): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ(! debug ) Ġsuper . toString () Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ object Label Ġstates Ġand Ġstatuses :\ n " Ġ+ Ġstates . toList () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString ("\ n ", Ġpostfix Ġ= Ġ"\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġ"${ it . first } Ġ= Ġ${ it . second () }" Ġ} Ġ+ Ġ"$ statuses \ n " Ġ+ Ġall Series . join ToString ("\ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }