-
Notifications
You must be signed in to change notification settings - Fork 0
Lab 10
Use Android Jetpack apis to implement an MVVM UI architecture in our app.
-
In the
studyguide
package, create a new classStudyGuideViewModel
-
Make
StudyGuideViewModel
extendViewModel
- The
ViewModel
class will help us retain state across orientation changes and act as a layer of separation between our UI and Data application layers
- The
-
Create a property named
title
of typeMutableStateFlow<String>
and initialize it with a value of"Study Guide"
val title: MutableStateFlow<String> = MutableStateFlow("Study Guide")
- This property exposes an observable stream of data that we will then use to update our UI anytime the value changes
- This moves us further in the direction of an MVVM UI architecture
-
Within
StudyGuideFragment
create a propertyviewModel
and initialize it usingval viewModel: StudyGuideViewModel by viewModels()
- The call to
by viewModels()
is a delegate function coming from Android Jetpack - This delegate will ensure we get the same
Fragment
instance back acrossFragment
recreation - This is important for retaining state across configuration change
- The call to
-
Open
fragment_study_guide.xml
and provide an id namedtitleTextView
for theTextView
so we can update its value fromStudyGuideFragment
-
Override
onViewCreated()
withinStudyGuideFragment
-
onViewCreated()
will be called afteronCreateView()
- This can be a good place to do things like setup state collection of a
ViewModel
-
-
Within
onViewCreated()
, launch a new coroutine usinglifecycleScope.launch{}
.- This will provide us with a coroutine which can be used to asynchronously collect changes in our
title
StateFlow
- Coroutines can be thought of as "lightweight threads". They are Kotlin's primary primitive for performing non-blocking operations.
- By launching our coroutine within
lifecycleScope
, it will ensure that our state collection is only active for as long as theFragment
- This will provide us with a coroutine which can be used to asynchronously collect changes in our
-
Inside the call to
launch{}
, callrepeateOnLifecycle(Lifecycle.State.STARTED) {}
- Within this call, we can setup the collection of our UI state to ensure we only respond to UI changes while the
Fragment
is active on screen -
repeatOnLifecycle()
will cancel and re-launch as the lifecycle moves in and out of the target state. - This helps ensure we are not trying to update the UI while the app is in the background
- Within this call, we can setup the collection of our UI state to ensure we only respond to UI changes while the
-
Inside
repeatOnLifecycle{}
callcollect{}
onviewModel.title
and updatebinding.titleTextView
with the new title value -
Open
StudyGuideViewModel
and add aninit{}
block so we can run some code when ourViewModel
is instantiated -
Within
init{}
useviewModelScope.launch{}
to create a new coroutine. -
Make a call to
delay(3000)
to simulate an async operation by suspending the coroutine for 3 seconds- The
delay()
function, is a suspending function coming from the coroutines library. It suspends the coroutine for the specified period of time. It's similar toThread.sleep()
. However,delay()
does not block the entireThread
; only the coroutine.
- The
-
After the
delay()
call, update the value of thetitle
StateFlow
toStudy Guide Fragment
usingtitle.update { "Study Guide Fragment" }
-
Re-deploy the app and notice how the title
TextView
's value changes automatically after the 3 second delay -
Create a new
data
package in your root project directory -
Create a
Note
data class with the following propertiestitle: String
category: String
content: String
-
In
StudyGuideViewModel
, create a data classUiState
with the following propertiestitle: String
notes: List<Note>
-
Remove the existing
title
StateFlow
property, and replace it with a single property namedstate
of typeMutableStateFlow<UiState>
- Update the initial value to provide the initial
title
and an empty set ofNote
s. (We will display notes in the next labs.) - Refactor the updating of the title within
init
tostate.update { currentValue -> currentValue.copy(title = "Study Guide Fragment") }
- Update the
Flow
collection withinStudyGuideFragment
to bind the title from theUiState
- Update the initial value to provide the initial
- Update
MyNotesFragment
to use aViewModel
with aUiState
that controls the displayed titleTextView
- Update
NoteDetailFragment
to use aViewModel
with aUiState
that controls the displayed title, category, and content - Update
CreateNoteFragment
to use aViewModel
with aUiState
that controls the categories displayed in theSpinner
dropdown