/* Ċ Ġ* Ġ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 Ġcom . example . android . track mys leep quality . sleep tracker Ċ Ċ import Ġandroid . app . Application Ċ import Ġandroid . text . Sp anned Ċ import Ġandroidx . lifecycle . Android ViewModel Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . lifecycle . Transform ations Ċ import Ġcom . example . android . track mys leep quality . database . Sleep Database Dao Ċ import Ġcom . example . android . track mys leep quality . database . Sleep Night Ċ import Ġcom . example . android . track mys leep quality . format N ights Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Job Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . with Context Ċ Ċ /** Ċ Ġ* ĠViewModel Ġfor Ġ` Sleep Tracker Fragment `. Ċ Ġ* Ċ Ġ* Ġ@ param Ġdatabase Ġthe Ġ[ Sleep Database Dao ] Ġto Ġuse Ġto Ġaccess Ġthe Ġdatabase Ċ Ġ* Ġ@ param Ġapplication Ġthe Ġ[ Application ] Ġto Ġuse Ġto Ġaccess Ġresources Ċ Ġ*/ Ċ class ĠSleep Tracker ViewModel ( ĊĠĠĠĠĠĠĠ Ġval Ġdatabase : ĠSleep Database Dao , ĊĠĠĠĠĠĠĠ Ġapplication : ĠApplication Ċ ) Ġ: ĠAndroid ViewModel ( application ) Ġ{ ĊĊĠĠĠ Ġ/** ĠCor outine Ġvariables Ġ*/ ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠviewModel Job Ġallows Ġus Ġto Ġcancel Ġall Ġcor outines Ġstarted Ġby Ġthis ĠViewModel . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġvar ĠviewModel Job Ġ= ĠJob () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠA Ġ[ Coroutine Scope ] Ġthat Ġkeeps Ġtrack Ġof Ġall Ġcor outines Ġstarted Ġby Ġthis ĠViewModel . ĠBecause Ġwe ĊĠĠĠĠ Ġ* Ġpass Ġit Ġ[ viewModel Job ], Ġany Ġcoroutine Ġstarted Ġin Ġthis Ġscope Ġcan Ġbe Ġcancelled Ġby Ġcalling ĊĠĠĠĠ Ġ* Ġ` viewModel Job . cancel ()`. ĠBy Ġdefault , Ġall Ġcor outines Ġstarted Ġin Ġ[ ui Scope ] Ġwill Ġlaunch Ġin ĊĠĠĠĠ Ġ* Ġ[ Dispatch ers . Main ] Ġwhich Ġis Ġthe Ġmain Ġthread Ġon ĠAndroid . ĠThis Ġis Ġa Ġsensible Ġdefault Ġbecause ĊĠĠĠĠ Ġ* Ġmost Ġcor outines Ġstarted Ġby Ġa Ġ` ViewModel ` Ġupdate Ġthe ĠUI Ġafter Ġperforming Ġsome Ġprocessing . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġui Scope Ġ= ĠCor outine Scope ( Dispatch ers . Main Ġ+ ĠviewModel Job ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġlatest Ġ[ Sleep Night ] Ġread Ġback Ġfrom Ġthe Ġdatabase Ġif Ġa Ġsleep Ġrecording Ġis Ġin Ġprogress Ġ( the ĊĠĠĠĠ Ġ* Ġ` endTime Milli ` Ġand Ġ` startTime Milli ` Ġfields Ġare Ġequal ), Ġor Ġ` null ` Ġif Ġwe Ġare Ġnot Ġrecording Ġa ĊĠĠĠĠ Ġ* Ġsleep Ġquality Ġ( the Ġlast Ġ[ Sleep Night ] Ġentered Ġthat Ġwe Ġread Ġby Ġcalling Ġthe Ġ` getT on ight ` Ġmethod ĊĠĠĠĠ Ġ* Ġof Ġ[ database ] Ġhad Ġdifferent Ġ` endTime Milli ` Ġand Ġ` startTime Milli ` Ġfields ). ĠWhen Ġnon - null Ġwe ĊĠĠĠĠ Ġ* Ġupdate Ġit Ġin Ġour Ġ[ on Stop Tracking ] Ġmethod Ġwhen Ġthe ĠSTOP Ġbutton Ġis Ġclicked . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġvar Ġton ight Ġ= ĠMutable LiveData < Sleep Night ?> () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġ[ LiveData ] Ġwrapped Ġlist Ġof Ġall Ġof Ġthe Ġ[ Sleep Night ] Ġentries Ġread Ġfrom Ġthe Ġdatabase . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġn ights Ġ= Ġdatabase . getAll N ights () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠConvert ed Ġ[ n ights ] Ġto Ġ[ Sp anned ] Ġfor Ġdisplaying . ĠWe Ġuse Ġthe Ġ[ Transform ations . map ] Ġmethod Ġto ĊĠĠĠĠ Ġ* Ġconvert Ġour Ġ[ LiveData ] Ġwrapped Ġlist Ġof Ġ[ Sleep Night ]' s Ġfield Ġ[ n ights ] Ġinto Ġa Ġ[ LiveData ] ĊĠĠĠĠ Ġ* Ġwrapped Ġ[ Sp anned ] Ġby Ġapplying Ġour Ġ[ format N ights ] Ġmethod Ġto Ġthe Ġvalue Ġin Ġ[ n ights ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġn ights String Ġ= ĠTransform ations . map ( n ights ) Ġ{ Ġn ights Ġ-> ĊĠĠĠĠĠĠĠ Ġformat N ights ( n ights , Ġapplication . resources ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġton ight Ġhas Ġnot Ġbeen Ġset , Ġthen Ġthe ĠSTART Ġbutton Ġshould Ġbe Ġvisible . ĠWe Ġuse Ġthe ĊĠĠĠĠ Ġ* Ġ[ Transform ations . map ] Ġmethod Ġto Ġconvert Ġour Ġ[ LiveData ] Ġwrapped Ġ[ Sleep Night ] Ġfield ĊĠĠĠĠ Ġ* Ġ[ ton ight ] Ġto Ġa Ġ[ LiveData ] Ġwrapped Ġ[ Boolean ] Ġwhich Ġis Ġ` true ` Ġif Ġ[ ton ight ] Ġis Ġ` null `. ĊĠĠĠĠ Ġ* ĠUsed Ġin Ġa Ġbinding Ġexpression Ġfor Ġthe Ġ" android : enabled " Ġattribute Ġof Ġthe Ġ` Button ` Ġwith ĊĠĠĠĠ Ġ* ĠID ĠR . id . start _ button Ġin Ġthe Ġfile Ġlayout / fragment _ sleep _ tracker . xml Ġ( the Ġlayout Ġfile Ġfor ĊĠĠĠĠ Ġ* Ġ` Sleep Tracker Fragment `). ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġstart Button Visible Ġ= ĠTransform ations . map ( ton ight ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnull Ġ== Ġit ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġton ight Ġhas Ġbeen Ġset , Ġthen Ġthe ĠSTOP Ġbutton Ġshould Ġbe Ġvisible . ĠWe Ġuse Ġthe ĊĠĠĠĠ Ġ* Ġ[ Transform ations . map ] Ġmethod Ġto Ġconvert Ġour Ġ[ LiveData ] Ġwrapped Ġ[ Sleep Night ] Ġfield ĊĠĠĠĠ Ġ* Ġ[ ton ight ] Ġto Ġa Ġ[ LiveData ] Ġwrapped Ġ[ Boolean ] Ġwhich Ġis Ġ` true ` Ġif Ġ[ ton ight ] Ġis Ġnot Ġ` null `. ĊĠĠĠĠ Ġ* ĠUsed Ġin Ġa Ġbinding Ġexpression Ġfor Ġthe Ġ" android : enabled " Ġattribute Ġof Ġthe Ġ` Button ` Ġwith ĊĠĠĠĠ Ġ* ĠID ĠR . id . stop _ button Ġin Ġthe Ġfile Ġlayout / fragment _ sleep _ tracker . xml Ġ( the Ġlayout Ġfile Ġfor ĊĠĠĠĠ Ġ* Ġ` Sleep Tracker Fragment `). ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġstop Button Visible Ġ= ĠTransform ations . map ( ton ight ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnull Ġ!= Ġit ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġthere Ġare Ġany Ġn ights Ġin Ġthe Ġdatabase , Ġshow Ġthe ĠCLEAR Ġbutton . ĠWe Ġuse Ġthe ĊĠĠĠĠ Ġ* Ġ[ Transform ations . map ] Ġmethod Ġto Ġconvert Ġour Ġ[ LiveData ] Ġwrapped Ġlist Ġof Ġ[ Sleep Night ] Ġfield ĊĠĠĠĠ Ġ* Ġ[ n ights ] Ġto Ġa Ġ[ LiveData ] Ġwrapped Ġ[ Boolean ] Ġwhich Ġis Ġ` true ` Ġif Ġ[ ton ight ] Ġis Ġnot Ġempty . ĊĠĠĠĠ Ġ* ĠUsed Ġin Ġa Ġbinding Ġexpression Ġfor Ġthe Ġ" android : enabled " Ġattribute Ġof Ġthe Ġ` Button ` Ġwith ĊĠĠĠĠ Ġ* ĠID ĠR . id . clear _ button Ġin Ġthe Ġfile Ġlayout / fragment _ sleep _ tracker . xml Ġ( the Ġlayout Ġfile Ġfor ĊĠĠĠĠ Ġ* Ġ` Sleep Tracker Fragment `). ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġclear Button Visible Ġ= ĠTransform ations . map ( n ights ) Ġ{ ĊĠĠĠĠĠĠĠ Ġit ?. isNotEmpty () ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRequest Ġa Ġ` Snackbar ` Ġby Ġsetting Ġthis Ġvalue Ġto Ġtrue . ĠThis Ġis Ġprivate Ġbecause Ġwe Ġdon 't Ġwant Ġto ĊĠĠĠĠ Ġ* Ġexpose Ġsetting Ġthis Ġvalue Ġto Ġthe ĠFragment , Ġpublicly Ġavailable Ġread - only Ġaccess Ġis Ġprovided ĊĠĠĠĠ Ġ* Ġby Ġ[ show Sn ackBar Event ]. ĠThis Ġis Ġset Ġto Ġ` true ` Ġby Ġour Ġ[ on Clear ] Ġmethod Ġand Ġset Ġto Ġ` null ` Ġby ĊĠĠĠĠ Ġ* Ġour Ġ[ done Showing Snackbar ] Ġmethod . Ġ[ on Clear ] Ġis Ġcalled Ġby Ġa Ġbinding Ġexpression Ġfor Ġthe ĊĠĠĠĠ Ġ* Ġ" android : onClick " Ġattribute Ġof Ġthe Ġ" Clear " Ġbutton Ġ( the Ġ` Button ` Ġwith ĠID ĠR . id . clear _ button Ġin ĊĠĠĠĠ Ġ* Ġthe Ġfile Ġlayout / fragment _ sleep _ tracker . xml ), Ġand Ġ[ done Showing Snackbar ] Ġis Ġcalled Ġby ĊĠĠĠĠ Ġ* Ġthe Ġ` Observer ` Ġadded Ġto Ġ[ show Sn ackBar Event ] Ġafter Ġit Ġshows Ġthe ĠSn ackbar . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġvar Ġ_ show Snackbar Event Ġ= ĠMutable LiveData < Boolean >() ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġthis Ġis Ġtrue , Ġimmediately Ġ` show ()` Ġa ĠSn ackbar Ġand Ġcall Ġ[ done Showing Snackbar ] Ġto Ġreset Ġto ĊĠĠĠĠ Ġ* Ġ` null `. ĠAn Ġ` Observer ` Ġis Ġadded Ġto Ġit Ġin Ġthe Ġ` onCreate View ` Ġoverride Ġof Ġ` Sleep Tracker Fragment ` ĊĠĠĠĠ Ġ* Ġwhich Ġshows Ġa ĠSn ackbar Ġinform ing Ġthe Ġuser Ġ" All Ġyour Ġdata Ġis Ġgone Ġforever " ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġshow Sn ackBar Event : ĠLive Data < Boolean > ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ show Snackbar Event ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠVariable Ġthat Ġtells Ġthe ĠFragment Ġto Ġnavigate Ġto Ġ` Sleep Quality Fragment ` Ġusing Ġthe Ġspecified ĊĠĠĠĠ Ġ* Ġ[ Sleep Night ] Ġas Ġthe Ġsafe Ġargs Ġfor Ġthe Ġfragment . ĠThis Ġis Ġprivate Ġbecause Ġwe Ġdon 't Ġwant Ġto ĊĠĠĠĠ Ġ* Ġexpose Ġsetting Ġthis Ġvalue Ġto Ġthe ĠFragment . ĠSet Ġto Ġthe Ġvalue Ġof Ġour Ġ[ ton ight ] Ġif Ġit Ġis Ġnot ĊĠĠĠĠ Ġ* Ġ` null ` Ġby Ġour Ġ[ on Stop Tracking ] Ġmethod Ġwhich Ġis Ġcalled Ġby Ġa Ġbinding Ġexpression Ġfor Ġthe ĊĠĠĠĠ Ġ* Ġ" android : onClick " Ġattribute Ġof Ġthe Ġ" Stop " Ġbutton Ġ( the Ġ` Button ` Ġwith ĠID ĠR . id . stop _ button Ġin ĊĠĠĠĠ Ġ* Ġthe Ġfile Ġlayout / fragment _ sleep _ tracker . xml ). ĠSet Ġto Ġ` null ` Ġby Ġour Ġ[ done Navig ating ] Ġmethod ĊĠĠĠĠ Ġ* Ġwhich Ġis Ġcalled Ġafter Ġnavig ating Ġto Ġthe Ġ` Sleep Quality Fragment ` Ġto Ġprevent Ġrepeated Ġnavig ating . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġ_ navigate To Sleep Quality Ġ= ĠMutable LiveData < Sleep Night ?> () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIf Ġthis Ġis Ġnon - null , Ġimmediately Ġnavigate Ġto Ġ` Sleep Quality Fragment ` Ġand Ġcall Ġ[ done Navig ating ]. ĊĠĠĠĠ Ġ* ĠAn Ġ` Observer ` Ġis Ġadded Ġto Ġit Ġin Ġthe Ġ` onCreate View ` Ġoverride Ġof Ġ` Sleep Tracker Fragment ` Ġwhich ĊĠĠĠĠ Ġ* Ġnavig ates Ġto Ġ` Sleep Quality Fragment ` Ġusing Ġthe Ġ` night Id ` Ġprimary Ġkey Ġof Ġthe Ġ[ Sleep Night ] Ġwe ĊĠĠĠĠ Ġ* Ġhold Ġas Ġthe Ġsafe Ġargs Ġto Ġpass . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġnavigate To Sleep Quality : ĠMutable LiveData < Sleep Night ?> ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ navigate To Sleep Quality ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCall Ġthis Ġimmediately Ġafter Ġcalling Ġ` show ()` Ġon Ġa ĠSn ackbar . ĠIt Ġwill Ġclear Ġthe ĠSn ackbar Ġrequest , ĊĠĠĠĠ Ġ* Ġso Ġif Ġthe Ġuser Ġrot ates Ġtheir Ġphone Ġit Ġwon 't Ġshow Ġa Ġduplicate ĠSn ackbar . ĠCalled Ġby Ġthe Ġ` Observer ` ĊĠĠĠĠ Ġ* Ġadded Ġto Ġour Ġ[ show Sn ackBar Event ] Ġfield Ġin Ġthe Ġ` onCreate View ` Ġoverride Ġof Ġ` Sleep Tracker Fragment ` ĊĠĠĠĠ Ġ* Ġafter Ġit Ġshows Ġits ĠSn ackbar . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdone Showing Snackbar () Ġ{ ĊĠĠĠĠĠĠĠ Ġ_ show Snackbar Event . value Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCall Ġthis Ġimmediately Ġafter Ġnavig ating Ġto Ġ` Sleep Quality Fragment `. ĠIt Ġwill Ġclear Ġthe Ġnavigation ĊĠĠĠĠ Ġ* Ġrequest , Ġso Ġif Ġthe Ġuser Ġrot ates Ġtheir Ġphone Ġit Ġwon 't Ġnavigate Ġtwice . ĠCalled Ġby Ġthe ĠObserver ĊĠĠĠĠ Ġ* Ġadded Ġto Ġour Ġ[ navigate To Sleep Quality ] Ġfield Ġin Ġthe Ġ` onCreate View ` Ġoverride Ġof ĊĠĠĠĠ Ġ* Ġ` Sleep Tracker Fragment ` Ġafter Ġif Ġnavig ates Ġto Ġ` Sleep Quality Fragment `. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdone Navig ating () Ġ{ ĊĠĠĠĠĠĠĠ Ġ_ navigate To Sleep Quality . value Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġinitialize T on ight () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġby Ġour Ġ` init ` Ġblock Ġto Ġinitialize Ġour Ġ[ ton ight ] Ġfield Ġto Ġthe Ġlast Ġentry Ġadded Ġto Ġthe ĊĠĠĠĠ Ġ* Ġdatabase Ġiff Ġit Ġrepresents Ġa Ġ[ Sleep Night ] Ġin Ġprogress Ġ(` endTime Milli ` Ġ== Ġ` startTime Milli `), ĊĠĠĠĠ Ġ* Ġor Ġto Ġ` null ` Ġif Ġthey Ġare Ġdifferent Ġ( the Ġlast Ġentry Ġis Ġa Ġcompleted Ġ[ Sleep Night ]). ĠWe Ġjust ĊĠĠĠĠ Ġ* Ġlaunch Ġa Ġcoroutine Ġon Ġthe Ġ[ ui Scope ] Ġ` Coroutine Scope ` Ġwhich Ġsets Ġthe Ġvalue Ġof Ġ[ ton ight ] Ġto ĊĠĠĠĠ Ġ* Ġthe Ġvalue Ġreturned Ġby Ġour Ġsuspend Ġfunction Ġ[ getT on ight From Database ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġinitialize T on ight () Ġ{ ĊĠĠĠĠĠĠĠ Ġui Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġton ight . value Ġ= Ġget T on ight From Database () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠHandling Ġthe Ġcase Ġof Ġthe Ġstopped Ġapp Ġor Ġforgot ten Ġrecording , Ġwhen Ġthe Ġstart Ġand Ġend Ġtimes ĊĠĠĠĠ Ġ* Ġwill Ġbe Ġthe Ġsame . ĠIf Ġthe Ġstart Ġtime Ġand Ġend Ġtime Ġare Ġnot Ġthe Ġsame , Ġthen Ġwe Ġdo Ġnot Ġhave Ġan ĊĠĠĠĠ Ġ* Ġun finished Ġrecording Ġso Ġwe Ġreturn Ġ` null `. ĠWe Ġcall Ġa Ġsus pending Ġblock Ġwith Ġthe Ġcoroutine ĊĠĠĠĠ Ġ* Ġcontext Ġof Ġ[ Dispatch ers . IO ], Ġsus pending Ġuntil Ġit Ġcompletes . ĠThe Ġsus pending Ġblock Ġlambda Ġsets ĊĠĠĠĠ Ġ* Ġthe Ġ[ Sleep Night ] Ġvariable Ġ` var Ġnight ` Ġto Ġthe Ġ[ Sleep Night ] Ġreturned Ġby Ġthe Ġ` getT on ight ` Ġmethod ĊĠĠĠĠ Ġ* Ġof Ġ[ database ]. ĠIt Ġthe Ġ` endTime Milli ` Ġfield Ġof Ġ` night ` Ġis Ġnot Ġequal Ġto Ġits Ġ` startTime Milli ` ĊĠĠĠĠ Ġ* Ġfield Ġwe Ġset Ġ` night ` Ġto Ġ` null `. ĠWhen Ġthe Ġlambda Ġcompletes Ġwe Ġreturn Ġits Ġ` night ` Ġvariable Ġto ĊĠĠĠĠ Ġ* Ġthe Ġcaller . ĠCalled Ġby Ġour Ġ[ initialize T on ight ] Ġmethod Ġand Ġby Ġour Ġ[ onStart Tracking ] Ġmethod Ġwhen ĊĠĠĠĠ Ġ* Ġthe Ġuser Ġclicks Ġthe Ġ" Start " Ġbutton Ġ( a Ġbinding Ġexpression Ġfor Ġthe Ġ" android : onClick " Ġattribute ĊĠĠĠĠ Ġ* Ġof Ġthe Ġbutton Ġcalls Ġ[ onStart Tracking ]). ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġlast Ġ[ Sleep Night ] Ġadded Ġto Ġthe Ġdatabase Ġif Ġits Ġ` endTime Milli ` Ġand Ġ` startTime Milli ` ĊĠĠĠĠ Ġ* Ġare Ġthe Ġsame Ġ( a Ġsleep Ġrecording Ġin Ġprogress ) Ġor Ġ` null ` Ġif Ġthey Ġdiffer . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġget T on ight From Database (): ĠSleep Night ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġnight Ġ= Ġdatabase . getT on ight () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( night ?. endTime Milli Ġ!= Ġnight ?. startTime Milli ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnight Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnight ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠInser ts Ġits Ġ[ Sleep Night ] Ġparameter Ġ[ night ] Ġinto Ġthe Ġdatabase . ĠWe Ġcall Ġa Ġsus pending Ġblock Ġwith ĊĠĠĠĠ Ġ* Ġthe Ġcoroutine Ġcontext Ġof Ġ[ Dispatch ers . IO ], Ġsus pending Ġuntil Ġit Ġcompletes . ĠThe Ġsus pending Ġblock ĊĠĠĠĠ Ġ* Ġlambda Ġcalls Ġthe Ġ` insert ` Ġmethod Ġof Ġ[ database ] Ġto Ġinsert Ġour Ġ[ Sleep Night ] Ġparameter Ġ[ night ] ĊĠĠĠĠ Ġ* Ġinto Ġthe Ġdatabase . ĠCalled Ġby Ġour Ġ[ onStart Tracking ] Ġmethod Ġwith Ġa Ġnewly Ġconstructed Ġ[ Sleep Night ]. ĊĠĠĠĠ Ġ* ĠA Ġbinding Ġexpression Ġfor Ġthe Ġ" android : onClick " Ġattribute Ġof Ġthe Ġ" Start " Ġbutton Ġcalls ĊĠĠĠĠ Ġ* Ġ[ onStart Tracking ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġnight Ġthe Ġ[ Sleep Night ] Ġto Ġinsert Ġinto Ġthe Ġdatabase . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġinsert ( night : ĠSleep Night ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . insert ( night ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠUpdates Ġits Ġ[ Sleep Night ] Ġparameter Ġ[ night ] Ġin Ġthe Ġdatabase Ġif Ġit Ġalready Ġexists Ġ( checked Ġby ĊĠĠĠĠ Ġ* Ġprimary Ġkey ). ĠWe Ġcall Ġa Ġsus pending Ġblock Ġwith Ġthe Ġcoroutine Ġcontext Ġof Ġ[ Dispatch ers . IO ], ĊĠĠĠĠ Ġ* Ġsus pending Ġuntil Ġit Ġcompletes . ĠThe Ġsus pending Ġblock Ġlambda Ġcalls Ġthe Ġ` update ` Ġmethod Ġof ĊĠĠĠĠ Ġ* Ġ[ database ] Ġto Ġupdate Ġour Ġ[ Sleep Night ] Ġparameter Ġ[ night ]' s Ġentry Ġin Ġthe Ġdatabase . ĠCalled Ġby ĊĠĠĠĠ Ġ* Ġour Ġ[ on Stop Tracking ] Ġmethod Ġwith Ġa Ġmodified Ġcopy Ġof Ġthe Ġ[ ton ight ] Ġfield Ġ( its Ġ` endTime Milli ` ĊĠĠĠĠ Ġ* Ġfield Ġhas Ġbeen Ġupdated Ġto Ġthe Ġcurrent Ġtime Ġin Ġmilliseconds ). Ġ[ on Stop Tracking ] Ġis Ġcalled Ġby Ġa ĊĠĠĠĠ Ġ* Ġbinding Ġexpression Ġfor Ġthe Ġ" android : onClick " Ġattribute Ġof Ġthe Ġ" STOP " Ġbutton Ġin Ġthe Ġlayout ĊĠĠĠĠ Ġ* Ġfile Ġlayout / fragment _ sleep _ tracker . xml Ġwhen Ġthe Ġuser Ġclicks Ġthat Ġbutton . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġnight Ġthe Ġ[ Sleep Night ] Ġobject Ġwhose Ġentry Ġin Ġthe Ġdatabase Ġshould Ġbe Ġupdated . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġupdate ( night : ĠSleep Night ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . update ( night ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDeletes Ġall Ġvalues Ġfrom Ġthe Ġ" daily _ sleep _ quality _ table " Ġtable Ġwithout Ġdeleting Ġthe Ġtable ĊĠĠĠĠ Ġ* Ġitself . ĠWe Ġcall Ġa Ġsus pending Ġblock Ġwith Ġthe Ġcoroutine Ġcontext Ġof Ġ[ Dispatch ers . IO ], ĊĠĠĠĠ Ġ* Ġsus pending Ġuntil Ġit Ġcompletes . ĠThe Ġsus pending Ġblock Ġlambda Ġcalls Ġthe Ġ` clear ` Ġmethod Ġof ĊĠĠĠĠ Ġ* Ġ[ database ] Ġto Ġdelete Ġall Ġvalues Ġfrom Ġthe Ġ" daily _ sleep _ quality _ table " Ġtable . ĠCalled Ġby Ġour ĊĠĠĠĠ Ġ* Ġ[ on Clear ] Ġmethod Ġwhich Ġis Ġcalled Ġby Ġa Ġbinding Ġexpression Ġfor Ġthe Ġ" android : onClick " Ġattribute ĊĠĠĠĠ Ġ* Ġof Ġthe Ġ" CLEAR " Ġbutton Ġin Ġthe Ġlayout Ġfile Ġlayout / fragment _ sleep _ tracker . xml Ġwhen Ġthe Ġuser ĊĠĠĠĠ Ġ* Ġclicks Ġthat Ġbutton . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġclear () Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . clear () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStarts Ġthe Ġrecording Ġof Ġa Ġnew Ġ[ Sleep Night ] Ġentry . ĠWe Ġlaunch Ġa Ġnew Ġcoroutine Ġwithout Ġblocking ĊĠĠĠĠ Ġ* Ġthe Ġcurrent Ġthread Ġusing Ġthe Ġ[ Coroutine Scope ] Ġof Ġ[ ui Scope ], Ġinitializing Ġour Ġ[ Sleep Night ] ĊĠĠĠĠ Ġ* Ġvariable Ġ` val Ġnew Night ` Ġwith Ġa Ġnew Ġinstance Ġof Ġ[ Sleep Night ] Ġ( the Ġconstructor Ġcaptures Ġthe ĊĠĠĠĠ Ġ* Ġcurrent Ġtime Ġin Ġboth Ġits Ġ` startTime Milli ` Ġand Ġ` endTime Milli ` Ġfields ). ĠWe Ġthen Ġcall Ġour ĊĠĠĠĠ Ġ* Ġsuspend Ġfunction Ġ[ insert ] Ġto Ġhave Ġit Ġinsert Ġ` new Night ` Ġinto Ġthe Ġdatabase . ĠWe Ġthen Ġset Ġthe ĊĠĠĠĠ Ġ* Ġvalue Ġof Ġour Ġ` Mutable LiveData < Sleep Night ?> ` Ġfield Ġ[ ton ight ] Ġto Ġthe Ġvalue Ġthat Ġour Ġsuspend ĊĠĠĠĠ Ġ* Ġfunction Ġ[ getT on ight From Database ] Ġreads Ġback Ġfrom Ġthe Ġdatabase Ġ( it Ġreads Ġthe Ġlast Ġ[ Sleep Night ] ĊĠĠĠĠ Ġ* Ġinserted Ġinto Ġthe Ġdatabase , Ġit Ġis Ġnecessary Ġto Ġdo Ġthis Ġbecause ĠRoom Ġauto - gener ates Ġthe Ġprimary ĊĠĠĠĠ Ġ* Ġkey Ġ` night Id ` Ġwhen Ġit Ġinserts Ġa Ġ[ Sleep Night ] Ġinto Ġthe Ġdatabase ). ĠExec utes Ġwhen Ġthe ĠSTART ĊĠĠĠĠ Ġ* Ġbutton Ġis Ġclicked Ġbecause Ġof Ġa Ġbinding Ġexpression Ġfor Ġthe Ġ" android : onClick " Ġattribute Ġof Ġthe ĊĠĠĠĠ Ġ* Ġbutton ĠR . id . start _ button Ġin Ġthe Ġlayout Ġfile Ġlayout / fragment _ sleep _ tracker . xml ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun ĠonStart Tracking () Ġ{ ĊĠĠĠĠĠĠĠ Ġui Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCreate Ġa Ġnew Ġnight , Ġwhich Ġcaptures Ġthe Ġcurrent Ġtime , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġand Ġinsert Ġit Ġinto Ġthe Ġdatabase . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Night Ġ= ĠSleep Night () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert ( new Night ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġton ight . value Ġ= Ġget T on ight From Database () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSto ps Ġthe Ġrecording Ġof Ġthe Ġpresent Ġ[ Sleep Night ] Ġentry . ĠWe Ġlaunch Ġa Ġnew Ġcoroutine Ġwithout ĊĠĠĠĠ Ġ* Ġblocking Ġthe Ġcurrent Ġthread Ġusing Ġthe Ġ[ Coroutine Scope ] Ġof Ġ[ ui Scope ], Ġinitializing Ġour ĊĠĠĠĠ Ġ* Ġ[ Sleep Night ] Ġvariable Ġ` val Ġold Night ` Ġwith Ġthe Ġvalue Ġof Ġour Ġ` Mutable LiveData < Sleep Night ?> ` ĊĠĠĠĠ Ġ* Ġfield Ġ[ ton ight ] Ġif Ġit Ġis Ġnot Ġ` null ` Ġand Ġreturning Ġfrom Ġthe Ġ` launch ` Ġhaving Ġdone Ġnothing Ġif ĊĠĠĠĠ Ġ* Ġit Ġis Ġ` null `. ĠContinu ing Ġwith Ġa Ġnon - null Ġ` old Night ` Ġwe Ġset Ġthe Ġ` endTime Milli ` Ġfield Ġof ĊĠĠĠĠ Ġ* Ġ` old Night ` Ġto Ġthe Ġcurrent Ġtime . ĠWe Ġthen Ġcall Ġour Ġsuspend Ġfunction Ġ[ update ] Ġto Ġhave Ġit Ġupdate ĊĠĠĠĠ Ġ* Ġthe Ġ` old Night ` Ġentry Ġin Ġthe Ġdatabase . ĠUp on Ġres uming Ġwe Ġset Ġthe Ġvalue Ġof Ġour Ġ[ Mutable LiveData ] ĊĠĠĠĠ Ġ* Ġwrapped Ġ[ Sleep Night ] Ġfield Ġ[_ navigate To Sleep Quality ] Ġto Ġ` old Night ` Ġwhich Ġwill Ġtrigger Ġthe ĊĠĠĠĠ Ġ* Ġnavigation Ġto Ġthe Ġ` Sleep Quality Fragment ` Ġthanks Ġto Ġan Ġ` Observer ` Ġof Ġ[ navigate To Sleep Quality ] ĊĠĠĠĠ Ġ* Ġadded Ġto Ġit Ġin Ġthe Ġ` onCreate View ` Ġoverride Ġof Ġ` Sleep Tracker Fragment `. ĊĠĠĠĠ Ġ* ĠExec utes Ġwhen Ġthe ĠSTOP Ġbutton Ġis Ġclicked Ġbecause Ġof Ġa Ġbinding Ġexpression Ġfor Ġthe ĊĠĠĠĠ Ġ* Ġ" android : onClick " Ġattribute Ġof Ġthe Ġbutton ĠR . id . stop _ button Ġin Ġthe Ġlayout Ġfile ĊĠĠĠĠ Ġ* Ġlayout / fragment _ sleep _ tracker . xml ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġon Stop Tracking () Ġ{ ĊĠĠĠĠĠĠĠ Ġui Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn ĠKotlin , Ġthe Ġreturn @ label Ġsyntax Ġis Ġused Ġfor Ġspecifying Ġwhich Ġfunction Ġamong ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġseveral Ġnested Ġones Ġthis Ġstatement Ġreturns Ġfrom . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn Ġthis Ġcase , Ġwe Ġare Ġspecifying Ġto Ġreturn Ġfrom Ġlaunch (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnot Ġthe Ġlambda . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġold Night Ġ= Ġton ight . value Ġ?: Ġreturn @ launch ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUpdate Ġthe Ġnight Ġin Ġthe Ġdatabase Ġto Ġadd Ġthe Ġend Ġtime . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġold Night . endTime Milli Ġ= ĠSystem . currentTimeMillis () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate ( old Night ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSet Ġstate Ġto Ġnavigate Ġto Ġthe ĠSleep Quality Fragment . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ navigate To Sleep Quality . value Ġ= Ġold Night ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDeletes Ġall Ġvalues Ġfrom Ġthe Ġ" daily _ sleep _ quality _ table " Ġtable Ġwithout Ġdeleting Ġthe Ġtable ĊĠĠĠĠ Ġ* Ġitself . ĠWe Ġlaunch Ġa Ġnew Ġcoroutine Ġwithout Ġblocking Ġthe Ġcurrent Ġthread Ġusing Ġthe Ġ[ Coroutine Scope ] ĊĠĠĠĠ Ġ* Ġof Ġ[ ui Scope ] Ġand Ġcall Ġour Ġsuspend Ġfunction Ġ[ clear ] Ġto Ġclear Ġthe Ġdatabase Ġtable . ĠOn Ġres uming ĊĠĠĠĠ Ġ* Ġwe Ġset Ġthe Ġvalue Ġof Ġour Ġ` Mutable LiveData < Sleep Night ?> ` Ġfield Ġ[ ton ight ] Ġto Ġ` null ` Ġ( since Ġit 's ĊĠĠĠĠ Ġ* Ġno Ġlonger Ġin Ġthe Ġdatabase ), Ġand Ġset Ġour Ġ[ Mutable LiveData ] Ġwrapped Ġ[ Boolean ] Ġfield Ġ[_ show Snackbar Event ] ĊĠĠĠĠ Ġ* Ġto Ġ` true ` Ġcausing Ġan Ġ` Observer ` Ġof Ġ[ show Sn ackBar Event ] Ġadded Ġto Ġit Ġin Ġthe Ġ` onCreate View ` Ġoverride ĊĠĠĠĠ Ġ* Ġof Ġ` Sleep Tracker Fragment ` Ġto Ġpost Ġa Ġ` Sn ackBar ` Ġinform ing Ġthe Ġuser Ġthat Ġhis Ġdata Ġis Ġgone . ĊĠĠĠĠ Ġ* ĠExec utes Ġwhen Ġthe ĠCLEAR Ġbutton Ġis Ġclicked Ġbecause Ġof Ġa Ġbinding Ġexpression Ġfor Ġthe ĊĠĠĠĠ Ġ* Ġ" android : onClick " Ġattribute Ġof Ġthe Ġbutton ĠR . id . clear _ button Ġin Ġthe Ġlayout Ġfile ĊĠĠĠĠ Ġ* Ġlayout / fragment _ sleep _ tracker . xml ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġon Clear () Ġ{ ĊĠĠĠĠĠĠĠ Ġui Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠClear Ġthe Ġdatabase Ġtable . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclear () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAnd Ġclear Ġton ight Ġsince Ġit 's Ġno Ġlonger Ġin Ġthe Ġdatabase ĊĠĠĠĠĠĠĠĠĠĠĠ Ġton ight . value Ġ= Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġa Ġsn ackbar Ġmessage , Ġbecause Ġit 's Ġfriendly . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ show Snackbar Event . value Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġwhen Ġthe ĠViewModel Ġis Ġdis m ant led . ĠAfter Ġcalling Ġour Ġsuper 's Ġimplementation Ġof Ġ` on Cle ared ` ĊĠĠĠĠ Ġ* Ġwe Ġcancel Ġall Ġcor outines Ġstarted Ġusing Ġour Ġ[ Coroutine Scope ] Ġfield Ġ[ ui Scope ] Ġby Ġcalling Ġthe ĊĠĠĠĠ Ġ* Ġ` cancel ` Ġmethod Ġof Ġour Ġ[ Job ] Ġfield Ġ[ viewModel Job ] Ġ( recall Ġthat Ġ[ ui Scope ] Ġuses Ġ[ viewModel Job ] ĊĠĠĠĠ Ġ* Ġas Ġpart Ġof Ġits Ġcoroutine Ġcontext ). ĠIf Ġwe Ġdon 't Ġdo Ġthis Ġwe Ġmight Ġend Ġup Ġwith Ġprocesses Ġthat ĊĠĠĠĠ Ġ* Ġhave Ġnow here Ġto Ġreturn Ġto Ġusing Ġmemory Ġand Ġresources . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon Cle ared () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Cle ared () ĊĠĠĠĠĠĠĠ ĠviewModel Job . cancel () ĊĠĠĠ Ġ} Ċ }