Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
25 views69 pages

AdvNative Week 4 - MVVM

Uploaded by

agissucida
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views69 pages

AdvNative Week 4 - MVVM

Uploaded by

agissucida
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 69

MVVM

Advanced Native Mobile Programming


Week 4
Teknik Informatika - Universitas Surabaya
Topics

◉ MVVM Concept
◉ Tutorial: View, Model, ViewModel

2
THE CONCEPT
Lifecycle, LiveData, MVVM 1 3
ACTIVITY LIFECYCLES

◉ Collection of callback
methods to inform object
state condition
◉ Activity, Fragment and
ViewModel has its own
lifecycle

4
FRAGMENT LIFECYCLES

◉ Fragment lifecycles more


complex
◉ Fragment must be attached
first
◉ At least need one activity to
hold/handle a fragment

5
COMPLEX MICRO MANAGEMENT

◉ Handle asynchronous calls


◉ Handle configuration changes
◉ Data update
◉ Memory leak problem
◉ Memory leaks occur when an application retains references to
objects that are no longer needed.

6
HANDLE ASYNCHRONOUS CALLS
◉ Asynchronous calls refer to any operation that does not
block the main thread and runs on a background thread.
◉ These operations include things like network requests,
database queries, and file I/O
◉ Asynchronous calls are important because they allow the
user interface to remain responsive while the app
performs time-consuming tasks.
◉ MVVM separate UI and business logic. In this case the VM
(View Model) can orchestrate asynchronous calls, handle
data transformations, and prepare data for presentation on
separate way.

7
HANDLE CONFIGURATION CHANGES

◉ Configuration changes occur when the user rotates the


screen, switches between portrait and landscape mode,
or changes the device's language.
◉ Without MVVM architecture, the MainActivity would be
destroyed and recreated
◉ Without the MVVM architecture, configuration changes can
result in data loss and poor user experience.

8
DATA UPDATE
◉ In traditional Android development without architectural
patterns, it was common for business logic, data retrieval,
and UI code to be tightly coupled within Activities and
Fragments
◉ Developers had to manually update UI components,
leading to potential inconsistencies and bugs
◉ Developers had to duplicate code for data retrieval and UI
updates across different parts of the app.

9
VIEWMODEL LIFECYCLES

◉ ViewModel encapsulate the data


for a UI controller to let the data
survive configuration changes
◉ ViewModel offer much more simple
lifecycles. ViewModel have one
method to handle those state
◉ ViewModel is lifecycle aware
(handling configuration change,
prevent memory leak, and data
update)

10
LIVEDATA

◉ Observable is an object that emit


value/data
◉ Observer is attached to the
observable and receive the data that
observable emit
◉ LiveData is an observable data
holder class and its lifecycle-aware
◉ LiveData only notifies active
observers about updates (and
livedata aware that)

11
LIVEDATA

◉ No memory leaks
◉ Always up to date data
◉ Manages configuration
changes

12
MVVM
Model View View Model Architecture

13
MVVM ARCHITECTURE

◉ Without architecture -> all UI logic and I/O logic handle by


single activity -> God Object
◉ Provide a way to structure our code in a way that provides
some advantages in this terms: separate the business and
presentation logic from the UI (means that the model
donʼt need to know what view/view model doing)
◉ Itʼs associated with View, Model, and ViewModel

14
VIEW

View is responsible for


You can also execute UI
the layout structure
logic.
displayed on the screen.

15
MODEL

Usually we retrieve data


Model is a non-visual
from REST-API in form of
class that has the data to
JSON, or from internal
use
sqlite database (DAO)

16
VIEWMODEL

The ViewModel
View that receives the
implements the data
state change notification
and commands
determines whether to
connected to the View
apply the change
to notify the View of
state changes via
ViewModel prepare the
change notification
data for View
events.

17
MVVM ARCHITECTURE

18
THE TUTORIAL
Develop project that uses MVVM architecture 2 19
STUDENT LIST
A classic example of data in list

20
CREATE A NEW PROJECT

◉ Start a new Android Studio Project, name it as “AdvWeek4”


(for Giraffe, start with no Activity)
◉ For Giraffe, create a new empty views “MainActivity”. Make it
launcher.
◉ Create a new github repo with any name according to your
preferences
◉ Connect/establish the github repo to this project, and make
your first commit and push

21
SETUP DEPENDENCIES
◉ Now open the build.gradle (project), and add following config at
the top, donʼt sync now yet:
buildscript {
repositories {
google()
}
dependencies {
classpath
'androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3'
}
}

22
SETUP DEPENDENCIES

◉ Open build.gradle (module) and look at the plugins object


on top. Add following lines of configuration to enable safe
arguments:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'androidx.navigation.safeargs.kotlin'
}

23
COMPILED SDK

◉ Some of the codes requires SDK 34. Adjust compiled SDK in


gradle (module)
android {
namespace = "com.example.anmpstudent"
compileSdk = 34

24
SETUP DEPENDENCIES

◉ Open build.gradle (module) and add following dependencies on the


bottom part. After that please press sync now:

implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("com.google.android.material:material:1.11.0-alpha03")

We use material design 3 Swipe Refresh Layout will be


used later on this tutorial

25
SETUP MATERIAL DESIGN 3

◉ Open the themes.xml and adjust the parent theme to:


<style name="Theme.ANMPStudent" parent="Theme.Material3.DayNight">

◉ Open the themes.xml (night) and adjust the parent theme to:
<style name="Theme.ANMPStudent" parent="Theme.Material3.Dark">

26
THE VIEWS
3 27
CREATE PACKAGES

◉ Project should be structured in MVVM way to make it clear and


tidy
◉ Create three new packages “model”, “view”, and “viewmodel”
◉ Steps:
◉ Right click on package name > new > package
◉ Type package name

28
29
MOVE ACTIVITY

◉ According to MVVM architecture, every object that related with UI


logic must be placed inside “view” package
◉ This include activities
◉ Drag and drop current MainActivity.kt inside the “view”
◉ Go with the default and click “refactor”
◉ Build > rebuild project to see the changes

30
MOVE ACTIVITY

31
CREATE FRAGMENTS

◉ In “view” package, create two fragments:


◉ StudentListFragment
Layout -> fragment_student_list.xml
◉ StudentDetailFragment
Layout -> fragment_student_detail.xml

32
STUDENT LIST LAYOUT
◉ Delete the default “textview” and add “constraint layout”
◉ Open the xml codes to add following xml manually:
<FrameLayout . . . >
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.StudentListFragment">

<constraint layout. . . />

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>

33
SWIPE REFRESH LAYOUT
It detects the vertical swipe,
displays a distinctive progress
bar, and triggers callback
methods in your app (usually
initiate fetching data action)

34
ew
Vi
l er
yc
c
Re
ar
ress B
Prog

Text View

35
STUDENT LIST ITEM LAYOUT
◉ Recycler View needs item layout to render each data into the list
◉ Create a new layout, name it as “student_list_item”

36
IMAGE VIEW
◉ Make sure you delete the android:src attribute in image view
widget. Check the xml code.
◉ Find the scrCompat and replace the image with
ic_launcher_foreground

37
FRAGMENT STUDENT DETAIL
LAYOUT
Mostly its used TextInputLayout
with Material Design Outline
Style
@style/Widget.Material3.TextIn
putLayout.OutlinedBox

38
Id = actionStudentDetail

NAVIGATION GRAPH
Next create new navigation
graph, name it as
“main_navigation.xml”

Dont forget to rebuild after


finished

39
SETUP HOST FRAGMENT
◉ Open activity_main.xml, delete the
default text view.
◉ Drag and drop “nav host fragment”
◉ Choose the “main_navigation”
◉ Set it full widht and height
◉ Set id to “fragmentHost”

40
THE MODEL
4 41
CREATE MODEL
◉ Model is just simple file that hold “data” blueprint in form of data
class.
◉ Model may have more than one class
◉ Right click on package “model” > new > Kotlin/Class file
◉ Named it as “Model”, choose “File” and then press enter key

42
DATACLASS STUDENT

data class Student( ◉ To simplify things, our model only


val id:String?, accept “String”
val name:String?, ◉ dob is “date of birth”
val dob:String?,
val phone:String?,
val photoUrl:String?
)

43
CREATE ADAPTER
◉ To make Recycler View work as intended, than we need to supply
it with adapter
◉ Right click on “view” package > new > “Kotlin/File class”
◉ Named it as “StudentListAdapter”
◉ Choose “class”, and then press enter

Why this adapter put in the “View”


package? Why don't we put it in the
“Model” package?

44
This adapter requires ArrayList data of
Student

CREATE ADAPTER
class StudentListAdapter(val studentList:ArrayList<Student>) {
class StudentViewHolder(var view: View) : RecyclerView.ViewHolder(view)
}

This is an inner class that primarily used


by the adapter to update the UI

45
CREATE ADAPTER
class StudentListAdapter(val studentList:ArrayList<Student>)
:RecyclerView.Adapter<StudentListAdapter.StudentViewHolder>()
{
class StudentViewHolder(view: View) : RecyclerView.ViewHolder(view)
}

Extend the class to


RecyclerView.Adapter that requires the
innerclass “student view holder”

46
GET REFERENCE TO UI
class StudentListAdapter(val studentList:ArrayList<Student>)
:RecyclerView.Adapter<StudentListAdapter.StudentViewHolder>()
{
class StudentViewHolder(view: View):RecyclerView.ViewHolder(view) {
val txtID:TextView
val txtName:TextView Init block allows you to execute code
val btnDetail:Button when an instance of the class is created
or when an object is initialized.

init {
txtID = view.findViewById(R.id.txtID)
txtName = view.findViewById(R.id.txtName)
btnDetail = view.findViewById(R.id.btnDetail)
}
}
}

47
IMPLEMENTS ALL MEMBER
override fun onCreateViewHolder(parent: ViewGroup, viewType:
Int):StudentViewHolder {
}

override fun onBindViewHolder(holder: StudentViewHolder, position: Int) { }

override fun getItemCount(): Int {


return studentList.size
Use auto-complete helper from android
}
studio. Do not type these all manually!

48
CREATE VIEW HOLDER
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
StudentViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.student_list_item, parent, false)

return StudentViewHolder(view)
}

Load the views that will be rendered on


each item in the list

49
BIND VIEW HOLDER
override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
holder.view.txtID.text = studenList[position].id
holder.view.txtName.text = studenList[position].name
}

50
BUTTON DETAIL LISTENER
override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
holder.view.txtID.text = studenList[position].id
holder.view.txtName.text = studenList[position].name

holder.view.btnDetail.setOnClickListener {
val action = StudentListFragmentDirections.actionStudentDetail()
Navigation.findNavController(it).navigate(action)
}

Button Detail is used to navigate to the


Student Detail screen
}

51
UPDATE STUDENT LIST FUNCTION
The main purpose of this function is to “refresh” student data list

fun updateStudentList(newStudentList: ArrayList<Student>) {


studenList.clear()
studenList.addAll(newStudentList)
notifyDataSetChanged()
} tells the recycler view that every single
item should be updated.

52
THE VIEW MODEL
5 53
CREATE VIEW MODEL
◉ The ViewModel class is designed to store and manage UI-related
data in a lifecycle conscious way. View model provide a way to
emit the data to observer.
◉ Create a new Kotlin class in “viewmodel” package, named it as
“ListViewModel.kt”
◉ This ListViewModel is used as bridging operation between
student model and fragment list

54
Extends View Model

LISTVIEW MODEL
class ListViewModel:ViewModel() {
val studentsLD = MutableLiveData<ArrayList<Student>>()
val studentLoadErrorLD = MutableLiveData<Boolean>()
val loadingLD = MutableLiveData<Boolean>()

● studentsLD = live data that “emit”


students data (in list form) MutableLiveData is type of LiveData
● studentLoadErrorLD = live data that that updateable
“emit” error status (boolean)
● loadingLD = live data that “emit” data
loading status (boolean)

55
Copy from here:
https://pastebin.com/GUtGT9hG Hardcoded data. In the next lecture will
be replaced with actual data from
REFRESH FUNCTION external sources

fun refresh() {
val student1 =
Student("16055","Nonie","1998/03/28","5718444778","http://dummyimage.com/75x100.jpg/cc0000/ffffff")

val student2 =
Student("13312","Rich","1994/12/14","3925444073","http://dummyimage.com/75x100.jpg/5fa2dd/ffffff")

val student3 =
Student("11204","Dinny","1994/10/07","6827808747","http://dummyimage.com/75x100.jpg/5fa2dd/ffffff1")

val studentList:ArrayList<Student> = arrayListOf<Student>(student1, student2, student3)

studentsLD.value = studentList
studentLoadErrorLD.value = false
loadingLD.value = false
} Refresh function in real case used to
load data from server/local and prepare
livedata objects. Ready to be observed

56
USE VIEW MODEL
◉ Next step is to use the view model in StudentListFragment
◉ Open StudentListFragment.kt, create two object:

class StudentListFragment : Fragment() {


private lateinit var viewModel:ListViewModel
private val studentListAdapter = StudentListAdapter(arrayListOf())

57
Override onViewCreated, and then
initialize and call refresh function

INITIALIZE VIEW MODEL


viewModel = ViewModelProvider(this).get(ListViewModel::class.java)
viewModel.refresh()

val recView = view.findViewById<RecyclerView>(R.id.recView)


recView.layoutManager = LinearLayoutManager(context)
recView.adapter = studentListAdapter

observeViewModel()
Initalize the adapter

58
OBSERVE VIEW MODEL FUNCTION
This function set actions for observer about how to handle the
emitted data

fun observeViewModel() {
}

59
OBSERVE VIEW MODEL FUNCTION
fun observeViewModel() { This observe function is used to
“observe” Students data

viewModel.studentsLD.observe(viewLifecycleOwner, Observer {
studentListAdapter.updateStudentList(it)
})

}
Any program under the Observer Students LiveData (observable)
function will be executed if needed (ie. attached to this fragment (observer).
activity state changed, configuration Every time observer changes its state,
changed, etc) the observable emit the data

60
OBSERVE VIEW MODEL FUNCTION
viewModel.studentLoadErrorLD.observe(viewLifecycleOwner, Observer {
val txtError = view?.findViewById<TextView>(R.id.txtError)
if(it == true) {
txtError?.visibility = View.VISIBLE
} else {
txtError?.visibility = View.GONE
}
})
This observe “loading error” livedata.
For now its just use dummy data

61
OBSERVE VIEW MODEL FUNCTION
viewModel.loadingLD.observe(viewLifecycleOwner, Observer {
val progressLoad = view?.findViewById<ProgressBar>(R.id.progressLoad)
val recView = view?.findViewById<RecyclerView>(R.id.recView)
if(it == true) {
recView.visibility = View.GONE
progressLoad.visibility = View.VISIBLE
} else {
recView.visibility = View.VISIBLE
progressLoad.visibility = View.GONE
}
}) This observe “loading” livedata. For
now its just use dummy data

62
RESULTS
StudentListFragment (observer)
“subscribe” to ListViewModel
(livedata).

ListViewModel then emit the


array of student. Its observer
automatically update the UI by
populating the recyclerview
adapter

63
HOMEWORK
6 64
CREATE VIEW MODEL
◉ Create new ViewModel to handle the StudentDetailFragment
◉ Name it as “DetailViewModel.kt”

class DetailViewModel:ViewModel() {
val studentLD = MutableLiveData<Student>()

}
This DetailViewModel only handle
single Student Data

65
FETCH FUNCTION
◉ Create fetch function (it has same function like “refresh”)

class DetailViewModel:ViewModel() {
val studentLD = MutableLiveData<Student>()
Prepare single dummy data student
fun fetch() {
val student1 = Student("16055","Nonie","1998/03/28","5718444778",
"http://dummyimage.com/75x100.jpg/cc0000/ffffff")
studentLD.value = student1
}
}

66
USE THE DETAIL VIEW MODEL
Your job is to use this new view model in
StudentDetailFragment

Hints:
- call fetch function in StudentDetailFragment.kt
- make observer for the “Student” livedata
- Ignore button update
- use setText method to change the edit text value

67
DUE DATE
◉ You must commit + push not exceeding the date (see the due
date on ULS)
◉ Submit the github link to ULS

68
THANKS!
Any questions?
You can find me at
andre@staff.ubaya.ac.id

69

You might also like