/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 Ġ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 Ġandroidx . lifecycle Ċ Ċ import Ġkotlinx . coroutines . Coroutine Dispatcher Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Job Ċ import Ġkotlinx . coroutines . Runnable Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġkotlin . coroutines . Coroutine Context Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle Owner ]' s Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ċ Ġ* Ġ[ Lifecycle . State . CREATED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle Owner . when Created ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ= ĊĠĠĠ Ġlifecycle . when Created ( block ) Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ġ[ Lifecycle . State . CREATED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle . when Created ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ{ ĊĠĠĠ Ġreturn Ġwhen State At Least ( Lifecycle . State . CREATED , Ġblock ) Ċ } Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle Owner ]' s Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ċ Ġ* Ġ[ Lifecycle . State . STARTED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle Owner . when Started ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ= ĊĠĠĠ Ġlifecycle . when Started ( block ) Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ġ[ Lifecycle . State . STARTED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle . when Started ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ{ ĊĠĠĠ Ġreturn Ġwhen State At Least ( Lifecycle . State . STARTED , Ġblock ) Ċ } Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle Owner ]' s Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ċ Ġ* Ġ[ Lifecycle . State . RE SU MED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle Owner . when Res umed ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ= ĊĠĠĠ Ġlifecycle . when Res umed ( block ) Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġblock Ġwhen Ġthe Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ġ[ Lifecycle . State . RE SU MED ] Ġstate . Ċ Ġ* Ċ Ġ* Ġ@ see ĠLifecycle . when State At Least Ġfor Ġdetails Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle . when Res umed ( block : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT ): ĠT Ġ{ ĊĠĠĠ Ġreturn Ġwhen State At Least ( Lifecycle . State . RE SU MED , Ġblock ) Ċ } Ċ Ċ /** Ċ Ġ* ĠRuns Ġthe Ġgiven Ġ[ block ] Ġon Ġa Ġ[ Coroutine Dispatcher ] Ġthat Ġexecutes Ġthe Ġ[ block ] Ġon Ġthe Ġmain Ġthread Ċ Ġ* Ġand Ġsus p ends Ġthe Ġexecution Ġunless Ġthe Ġ[ Lifecycle ]' s Ġstate Ġis Ġat Ġleast Ġ[ min State ]. Ċ Ġ* Ċ Ġ* ĠIf Ġthe Ġ[ Lifecycle ] Ġmoves Ġto Ġa Ġless er Ġstate Ġwhile Ġthe Ġ[ block ] Ġis Ġrunning , Ġthe Ġ[ block ] Ġwill Ċ Ġ* Ġbe Ġsus pended Ġuntil Ġthe Ġ[ Lifecycle ] Ġreaches Ġto Ġa Ġstate Ġgreater Ġor Ġequal Ġto Ġ[ min State ]. Ċ Ġ* Ċ Ġ* ĠNote Ġthat Ġthis Ġwon 't Ġeffect Ġany Ġsub Ġcoroutine Ġif Ġthey Ġuse Ġa Ġdifferent Ġ[ Coroutine Dispatcher ]. Ċ Ġ* ĠHowever , Ġthe Ġ[ block ] Ġwill Ġnot Ġresume Ġexecution Ġwhen Ġthe Ġsub Ġcoroutine Ġfinishes Ġunless Ġthe Ċ Ġ* Ġ[ Lifecycle ] Ġis Ġat Ġleast Ġin Ġ[ min State ]. Ċ Ġ* Ċ Ġ* ĠIf Ġthe Ġ[ Lifecycle ] Ġis Ġdestroyed Ġwhile Ġthe Ġ[ block ] Ġis Ġsus pended , Ġthe Ġ[ block ] Ġwill Ġbe Ġcancelled Ċ Ġ* Ġwhich Ġwill Ġalso Ġcancel Ġany Ġchild Ġcoroutine Ġlaunched Ġinside Ġthe Ġ[ block ]. Ċ Ġ* Ċ Ġ* ĠIf Ġyou Ġhave Ġa Ġ` try Ġfinally ` Ġblock Ġin Ġyour Ġcode , Ġthe Ġ` finally ` Ġmight Ġrun Ġafter Ġthe Ġ[ Lifecycle ] Ċ Ġ* Ġmoves Ġoutside Ġthe Ġdesired Ġstate . ĠIt Ġis Ġrecommended Ġto Ġcheck Ġthe Ġ[ Lifecycle . getCurrent State ] Ċ Ġ* Ġbefore Ġaccessing Ġthe ĠUI . ĠSimilar ly , Ġif Ġyou Ġhave Ġa Ġ` catch ` Ġstatement Ġthat Ġmight Ġcatch Ċ Ġ* Ġ` Cancellation Exception `, Ġyou Ġshould Ġcheck Ġthe Ġ[ Lifecycle . getCurrent State ] Ġbefore Ġaccessing Ġthe Ċ Ġ* ĠUI . ĠSee Ġthe Ġsample Ġbelow Ġfor Ġmore Ġdetails . Ċ Ġ* Ċ Ġ* Ġ``` Ċ Ġ* Ġ// Ġrunning Ġa Ġblock Ġof Ġcode Ġonly Ġif Ġlifecycle Ġis ĠSTART ED Ċ Ġ* Ġview Lifecycle . when State At Least ( Lifecycle . State . STARTED ) Ġ{ Ċ Ġ* ĠĠĠĠ Ġ// Ġhere , Ġwe Ġare Ġon Ġthe Ġmain Ġthread Ġand Ġview Ġlifecycle Ġis Ġguaranteed Ġto Ġbe ĠSTART ED Ġor ĠRES U MED . Ċ Ġ* ĠĠĠĠ Ġ// ĠWe Ġcan Ġsafely Ġaccess Ġour Ġviews . Ċ Ġ* ĠĠĠĠ Ġloading Bar . visibility Ġ= ĠView . VISIBLE Ċ Ġ* ĠĠĠĠ Ġtry Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// Ġwe Ġcan Ġcall Ġany Ġsuspend Ġfunction Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġwith Context ( Dispatch ers . IO ) Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġwill Ġrun Ġin ĠIO Ġthread Ġpool . ĠIt Ġwill Ġkeep Ġrunning Ġas Ġlong Ġas ĠLifecycle Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġis Ġnot ĠDEST ROY ED . ĠIf Ġit Ġis Ġdestroyed , Ġthis Ġcoroutine Ġwill Ġbe Ġcancelled Ġas Ġwell . Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠHowever , Ġwe ĠCAN NOT Ġaccess ĠViews Ġhere . Ċ Ġ* Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġare Ġusing Ġwith Context ( Dispatch ers . IO ) Ġhere Ġjust Ġfor Ġdemonstr ation Ġpurposes . Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSuch Ġcode Ġshould Ġlive Ġin Ġyour Ġbusiness Ġlogic Ġclasses Ġand Ġyour ĠUI Ġshould Ġuse Ġa Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠViewModel Ġ( or Ġsimilar ) Ġto Ġaccess Ġit . Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġapi . getUser () Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ} Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġline Ġwill Ġexecute Ġon Ġthe Ġmain Ġthread Ġand Ġonly Ġif Ġthe Ġlifecycle Ġis Ġin Ġat Ġleast Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// ĠSTART ED Ġstate Ġ( STARTED Ġis Ġthe Ġparameter Ġwe 've Ġpassed Ġto Ġwhen State At Least ) Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// ĠBecause Ġof Ġthis Ġguarantee , Ġwe Ġcan Ġsafely Ġaccess Ġthe ĠUI Ġagain . Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġloading Bar . visibility Ġ= ĠView . GONE Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġname TextView . text Ġ= Ġuser . name Ċ Ġ* ĠĠĠĠĠĠĠĠ ĠlastName TextView . text Ġ= Ġuser . lastName Ċ Ġ* ĠĠĠĠ Ġ} Ġcatch ( ex Ġ: ĠUser NotFoundException ) Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// Ġsame Ġas Ġabove , Ġthis Ġcode Ġcan Ġsafely Ġaccess ĠUI Ġelements Ġbecause Ġit Ġonly Ġruns Ġif Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// Ġview Ġlifecycle Ġis Ġat Ġleast ĠSTART ED Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġloading Bar . visibility Ġ= ĠView . GONE Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġshow Error Dialog ( ex ) Ċ Ġ* ĠĠĠĠ Ġ} Ġcatch ( th Ġ: ĠThrowable ) Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠĠ Ġ// ĠUn like Ġthe Ġcatch Ġstatement Ġabove , Ġthis Ġcatch Ġstatements Ġit Ġtoo Ġgeneric Ġand Ġmight Ċ Ġ* ĠĠĠĠĠĠĠĠĠ Ġ// Ġalso Ġcatch Ġthe ĠC ancellation Exception . ĠBefore Ġaccessing ĠUI , Ġyou Ġshould Ġcheck ĠisActive Ċ Ġ* ĠĠĠĠĠĠĠĠĠ Ġ// Ġor Ġlifecycle Ġstate Ċ Ġ* ĠĠĠĠĠĠĠĠĠ Ġif Ġ( view Lifecycle . currentState Ġ>= ĠLifecycle . State . STARTED ) Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġhere Ġyou Ġcan Ġaccess Ġthe Ġview Ġbecause Ġyou 've Ġchecked Ġthe Ġcoroutine Ġis Ġactive Ċ Ġ* ĠĠĠĠĠĠĠĠĠ Ġ} Ċ Ġ* ĠĠĠĠ Ġ} Ġfinally Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// Ġin Ġcase Ġof Ġcancellation , Ġthis Ġline Ġmight Ġrun Ġeven Ġif Ġthe ĠLifecycle Ġis Ġnot ĠDEST ROY ED . Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ// ĠYou Ġcannot Ġaccess ĠViews Ġhere Ġunless Ġyou Ġcheck Ġ` isActive ` Ġor Ġlifecycle Ġstate Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġif Ġ( view Lifecycle . currentState Ġ>= ĠLifecycle . State . STARTED ) Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġsafe Ġto Ġaccess Ġviews Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ Ċ Ġ* ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnot Ġsafe Ġto Ġaccess Ġviews Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġ} Ċ Ġ* ĠĠĠĠ Ġ} Ċ Ġ* Ġ} Ċ Ġ* Ġ``` Ċ Ġ* Ċ Ġ* Ġ@ param Ġmin State ĠThe Ġdesired Ġminimum Ġstate Ġto Ġrun Ġthe Ġ[ block ]. Ċ Ġ* Ġ@ param Ġblock ĠThe Ġblock Ġto Ġrun Ġwhen Ġthe Ġlifecycle Ġis Ġat Ġleast Ġin Ġ[ min State ]. Ċ Ġ* Ġ@ return Ġ< T > ĠThe Ġreturn Ġvalue Ġof Ġthe Ġ[ block ] Ċ Ġ*/ Ċ public Ġsuspend Ġfun Ġ< T > ĠLifecycle . when State At Least ( ĊĠĠĠ Ġmin State : ĠLifecycle . State , ĊĠĠĠ Ġblock : Ġsuspend ĠCor outine Scope . () Ġ-> ĠT Ċ ): ĠT Ġ= Ġwith Context ( Dispatch ers . Main . immediate ) Ġ{ ĊĠĠĠ Ġval Ġjob Ġ= Ġcoroutine Context [ Job ] Ġ?: Ġerror (" when [ State ] Ġmethods Ġshould Ġhave Ġa Ġparent Ġjob ") ĊĠĠĠ Ġval Ġdispatcher Ġ= ĠPa using Dispatcher () ĊĠĠĠ Ġval Ġcontroller Ġ= ĊĠĠĠĠĠĠĠ ĠLifecycle Controller ( this @ when State At Least , Ġmin State , Ġdispatcher . dispatch Queue , Ġjob ) ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Context ( dispatcher , Ġblock ) ĊĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠ Ġcontroller . finish () ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠA Ġ[ Coroutine Dispatcher ] Ġimplementation Ġthat Ġmaintains Ġa Ġdispatch Ġqueue Ġto Ġbe Ġable Ġto Ġpause Ċ Ġ* Ġexecution Ġof Ġcor outines . Ċ Ġ* Ċ Ġ* Ġ@ see Ġ[ Dispatch Queue ] Ġand Ġ[ Lifecycle . when State At Least ] Ġfor Ġdetails . Ċ Ġ*/ Ċ internal Ġclass ĠPa using Dispatcher Ġ: ĠCor outine Dispatcher () Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġhelper Ġclass Ġto Ġmaintain Ġstate Ġand Ġen queued Ġcontinu ations . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Jvm Field ĊĠĠĠ Ġinternal Ġval Ġdispatch Queue Ġ= ĠDispatch Queue () ĊĊĠĠĠ Ġoverride Ġfun Ġis Dispatch Needed ( context : ĠCor outine Context ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Dispatch ers . Main . immediate . is Dispatch Needed ( context )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠIt 's Ġsafe Ġto Ġcall Ġdispatch Queue . can Run () Ġhere Ġbecause ĊĠĠĠĠĠĠĠ Ġ// ĠDispatch ers . Main . immediate . is Dispatch Needed Ġreturns Ġtrue Ġif Ġwe 're Ġnot Ġon Ġthe Ġmain Ġthread ĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġthe Ġqueue Ġis Ġpaused Ġright Ġnow Ġwe Ġneed Ġto Ġdispatch Ġso Ġthat Ġthe Ġblock Ġis Ġadded Ġto Ġthe ĊĠĠĠĠĠĠĠ Ġ// Ġthe Ġqueue ĊĠĠĠĠĠĠĠ Ġreturn Ġ! dispatch Queue . can Run () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġdispatch ( context : ĠCor outine Context , Ġblock : ĠRunnable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġdispatch Queue . dispatch And Enqueue ( context , Ġblock ) ĊĠĠĠ Ġ} Ċ } Ċ