0% found this document useful (0 votes)
25 views

Architectural Design Pattern Android

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 views

Architectural Design Pattern Android

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/ 169

Android Architectural

Design Patterns
About Course
• Duration (18 hours)
- 3 Lectures (9 hours)
- 3 Labs (9 hours)

• Evaluation Criteria
- 40% for labs
- 60% for projects
Why using Architecture?
Architectural design patterns
As the Android apps became more complex, developers began to think
which best practices available to make apps more extensible,
maintainable and testable.

App architecture patterns they all exist to help you design your app in
such a way that allows the app to be maintainable as it scales.

It focuses on two main concepts:


1. Separation of concerns and
2. Unit testing.
Separation of Concerns
Separation of concerns deals with separating the components of your
app by responsibility.

• For example, when you update the UI of your app with a fancy new
design, you want to do so without having to change any of the other
code, such as the underlying data.

As you add more features to your app, you want to do so without


having to change too much of your existing code.
Unit Testing
As your app grows, you want to be able to test the app to ensure you didn’t
break the logic of existing features.

Organizing your code into small pieces make it easier to be testable. Once it
became testable

The only way to go fast is to go well


-Robert C. Martin-
Architectural Design patterns
Android has four commonly used design patterns:
MVC, MVP, MVVM (commonly used) and MVI
Our Goal
To build a movie app :
Model View Controller (MVC)
Model View Controller
Model View Controller architecture separates components of a software system, based on
responsibilities.
In this pattern, three components with distinct responsibilities are defined as follows:

• Model is the data layer. This includes the data objects, database classes, and other
business logic, concerned with storing the data, retrieving the data, updating the data,
etc.

• View renders the data using the Model in a way suitable for user interface. It is what gets
displayed to the user.

• Controller is the brain of the system. It encapsulates the logic of the system, and it
controls both the Model and View. The user interacts with the system through this
controller.
MVC in Web / Desktop
When MVC was originally conceptualized, it was initially applied to
desktop and web applications. A typical application of this pattern in
the web realm would look like this
• The user inputs are HTTP requests.
• The Controller handles those 4
5
requests by updating the data in the
Model.
• The View returned to the user is a 1
3
rendered HTML page, displaying the
data. 2
Model View Controller
Because components are isolated from each other, each focused on
only one responsibility, the system is more flexible and modular.

Each component is able to be unit tested on its own and could be


swapped out for another version without affecting the other.
Applying MVC to Android
The entry point to the app is through the Controller

The Controller is the Android Activity where it can handle user inputs
(EditTexts and pressed buttons) and respond accordingly.

The Model consists of the data objects, which, in Android, are just regular
POJO Java bean classes, as well as the classes to handle data locally and
remotely.

The View consists of the layout files in an Android app.


Applying MVC to Android
Case Study
Favorite movies screen
• This screen can:
1. View stored movies
2. Delete a stored movie
Model
This includes the data objects (DTO, POJO, Bean), database classes, and
other business logic, concerned with storing the data, retrieving the
data, updating the data, etc. (same as before)

Model should not be concerned with how it’s ultimately displayed to


the user.

Model classes are simple classes which the other components can use.
Model
Model
Model Cont’d
View
View is what’s displayed to the user.
It should not be concerned with the values of the actual data it is
displaying, only that it needs to be displayed.

• A view should only be responsible for displaying things and should


not contain any business logic.

• It tends to be a lightweight component compared to a controller and


typically doesn’t contain much code.
View Cont’d
View Cont’d
Controller
• The Controller then acts as the glue between these two components,
orchestrating how the data should be displayed

• They connect models and views together.

• The controller updates the model when something happens in the view.
The controller will also update the view when the model changes.

• Too often, the controller responsibilities are also found in activities and
fragments.
Controller Cont’d
Android Follows MVC by Default
View - Logic Separation
Adapter is considered a way to organize data on the recycler view.
So, it is considered a part of the view.
In order to prevent having any logic in the view. We don’t provide any code in the
setOnClickListener () instead we we’ll keep the logic to the controller.

We delegate this responsibility to the controller.

To do this : 1. Create an interface with one method


2. Pass a reference of the interface to the Adapter Constructor
3. In the setOnClickListener invoke the method in the interface using
the passed reference
4. Make the required Controller implement this interface
View - Logic Separation
Adapter is considered a way to organize data on the recycler view.
So, it is considered a part of the view.
In order to prevent having any logic in the view. We don’t provide any code in the
setOnClickListener () instead we we’ll keep the logic to the controller.

We delegate this responsibility to the controller.

To do this : 1. Create an interface with one method


2. Pass a reference of the interface to the Adapter Constructor
3. In the setOnClickListener invoke the method in the interface using
the passed reference
4. Make the required Controller implement this interface
View - Logic Separation
1. Create an interface with one method

2. Pass a reference of the interface to the Adapter Constructor


View - Logic Separation Cont’d
3. In the setOnClickListener invoke the method in the interface using the passed reference
View - Logic Separation Cont’d
4. Make the required Controller implement this interface
Project Structure
Project Structure
Android applications should always be neatly organized with a clear
folder structure that makes your code easy to read. In addition, proper
naming conventions for code and classes are important to ensure your
code is clean and maintainable.

There are two commonly used techniques for organizing your app's
package structure.
1. Group by category.
2. Group by feature
Organize by features
• This allows you to place FavoriteActivity, FavoriteFragment,
FavoriteAdapter, FavoriteModel in one big package.

• Following this technique provides comfortable navigation when you're


working on “Favorite-Movies" feature.

• Inside the feature the files can be located under sub-packages for more
organization based on the architecture you’re following.

• When there are common packages that is used during the whole
application (not limited to only one feature) , these packages can stand
alone not following any feature i.e.: utils, model, network ..etc.
Organize by features

Favorite Movies feature is divided


into sub-packages (controller – view )
as we follow the MVC

Model is shared between the whole app


so it didn’t follow a specific feature
Retrofit CallBack
Case Study
All movies screen
• This screen can:
1. Show movies from network (our concern)
2. Store a movie to our favorites
Dealing with Network
Up till now our app can work fine with static data but that’s not always
the case.
In real world applications will require working with network for many
purposes a lot.
At the same time we want to keep the network code separated from
the controller. (Don’t forget separation of concern)

As a solution we can make the retrofit call in method and receive the
returned value.
When calling the start
method. The normal
result is :
No data retrieved!
Retrofit Callback
Retrofit enqueue CallBack to make our network calls.

These callbacks act as a promise that a result will return in some time
in the future (whether it is a successful result or not).

The problem: This callback will be executed asynchronously unlike our


function that will be executed synchronously.

We need to watch this response and execute the proper logic as soon
as the results arrive
Retrofit Callback
To handle this let’s:
1. Create an interface i.e: NetworkCallback
2. In the interface create the proper methods corresponding to
success or failure of the response.
3. Pass a reference from the interface type to the constructor /
Method of the network class.
4. when overriding onResponse and onFailure on the CallBack invoke
the proper methods in the interface using the provided reference
5. Now the proper controller should implement the interface to offer
the proper results to the view.
Retrofit Callback separation
1. Create an interface i.e: NetworkCallback
2. In the interface create the proper methods corresponding to success
or failure of the response.
Retrofit Callback separation Cont’d
3. Pass a reference from the interface type to the required method inside the network class.
Retrofit Callback separation Cont’d
4. when overriding onResponse and onFailure in the CallBack invoke the proper methods
in the interface using the provided reference
Inside MovieClient
Retrofit Callback separation Cont’d

5- Now the proper controller


should implement the
interface to offer the proper
results to the view.
Room
Room
The Room persistence library provides an abstraction layer over SQLite
to allow fluent database access while harnessing the full power of
SQLite.

Room provides the following benefits:


1. Compile-time verification of SQL queries.
2. Convenience annotations that minimize repetitive and error-
prone boilerplate code.
Room Components
Room has three primary components

Data entities that represent tables in your


app's database.

Data access objects (DAOs) that provide


methods that your app can use to make CRUD
operations in the database.

The database class that holds the database


and serves as the main access point for the
underlying connection to your app's persisted
data.
Case Study
In our movies app what operations do we need?
1. Add movie
2. Delete Movie
3. Show all Stored movies
How to Room
1. Add the proper dependencies from here
https://developer.android.com/training/data-storage/room
2. Mark your POJO with @Entity followed by required table name as
follows (tableName = “”)
3. Create a DAO interface that will contain the desired CRUD
operations
4. In this interface create methods for your operations annotating
them with the SQL operation
5. Create your database using the database builder
1. Adding Room Dependencies
implementation "androidx.room:room-runtime:2.4.1"
annotationProcessor "androidx.room:room-compiler:2.4.1"

2. Mark your POJO with @Entity


@Dao 3. Create a DAO interface that will
public interface MovieDAO { contain the desired CRUD operations

@Query("SELECT * FROM movies_table")


List<Movie> getAllMovies();

@Insert 4. In this interface create methods for


void insertMovie (Movie movie); your operations annotating them with the
SQL operation

@Delete
void deleteMovie (Movie movie);
}
5. Create your database
@Database(entities = {Movie.class}, version = 1) using the database
public abstract class AppDataBase extends RoomDatabase { builder
private static AppDataBase instance = null;
public abstract MovieDAO getMovieDAO();
public static synchronized AppDataBase getInstance(Context context){
if (instance == null){
instance = Room.databaseBuilder(context.getApplicationContext(), AppDataBase.class, "moviesdb")
.build();
}
return instance;
}
}
DataBase Inspector
Higher version of android studio (starting from 4.1 and above) enable database Inspector.

Database Inspector allows you to inspect, query, and modify your app's databases while
your app is running.
The Database Inspector works with plain SQLite and with libraries built on top of SQLite,
such as Room.

To open DataBase inspector:


1. Run your app on an emulator or connected device running API level 26 or higher.
2. Select View > Tool Windows > App Inspection from the menu bar.
3. Select the Database Inspector tab.
Remember your SQLite storage lab?
You could see the mobile and message through the app inspector like this image

Using SQLite

As Room is based on SQLite the same thing can be applied here too.
So you can check the real stored data.
Using Room

And you can find more: https://developer.android.com/studio/inspect/database


Demo
Observe Database
When data changes we usually want to take some action, such as
displaying the updated data in the UI. In our case we want to show the
updated version of the stored movies.
This means we have to observe the data so that when it changes, you
can react.

Observing changes to data across multiple components of your app can


create explicit, rigid dependency paths between the components.
This makes testing and debugging difficult, among other things.
LifeCycle Aware Components
LifeCycle Aware Components
Lifecycle-aware components perform actions in response to a change in the lifecycle status
of another component, such as activities and fragments. These components help you
produce better-organized, and often lighter-weight code, that is easier to maintain. For
example: LiveDate, MutableLiveData..etc.

By using them, you can move the code of dependent components out of the lifecycle
methods and into the components themselves.

We can build lifecycle-aware components—which are components that can automatically


adjust their behavior based on the current lifecycle state of an activity or fragment.

Lifecycles are managed by the operating system or the framework code running in your
process. They are core to how Android works and your application must respect them. Not
doing so may trigger memory leaks or even application crashes.
LifeCycle Owner
LifecycleOwner is a single method interface that denotes that the class has a Lifecycle. It has one
method, getLifecycle(), which must be implemented by the class.

Android provides built-in components that are lifecycle owners. For activities, ComponentActivity,
which is the base class for AppCompatActivity, is the one that implements LifecycleOwner.

Also, there are other classes that already implement this interface, too. For example, Fragment is a
LifecycleOwner

The lifecycle owner needs to know all the components that need to listen for its lifecycle changes.
Using the observer pattern is the best approach to achieve this.

For more implementation’s details you can read this article


https://www.raywenderlich.com/22025947-lifecycle-aware-components-using-android-jetpack#toc-
anchor-004
LiveData
LiveData is an example of a lifecycle-aware component that is already
available in Android.
• It’s an observable data holder class, which means it can contain data
and it will notify its observers when that data changes.
• As a lifecycle-aware component, it will only updates its observers
when the lifecycle is in an active state.
• LiveData is a wrapper on an object which can be observed from any
UI controller, such as an activity or fragment.
LiveData Advantages

• Ensures your UI matches your data state

• No memory leaks

• No crashes due to stopped activities

• No more manual lifecycle handling

• Proper configuration changes


Work with LiveData
To work with LiveData we follow these steps:
1. Wrap your data in a LiveData.
2. Create an Observer object that defines the onChanged().
3. Attach the Observer object to the LiveData object using observe()

LiveData doesn’t have public methods to update its value. But it has
subclasses that are eligible for doing so.
Apply LiveData to Room
• Now we can mix liveData and Room together to get our desired DAO

1
Observing LiveData

3 2
Behind The Scenes
MutableLiveData
The MutableLiveData class exposes the setValue(T) and postValue(T) methods
publicly and you must use these if you need to edit the value stored in a LiveData
object.

Usually MutableLiveData is used in cooperation with LiveData to only exposes


immutable LiveData objects to the observers.

Methods:
1. postValue() - Posts a task to a main thread to set the given value.
2. getValue() - Returns the current value.
3. observe() - Adds the given observer to the observers list within the lifespan of
the given owner.
Room with LiveData
The Room persistence library supports observable queries, which
return LiveData objects.
Observable queries are written as part of a Database Access Object
(DAO).

Room generates all the necessary code to update the LiveData object
when a database is updated.
The generated code runs the query asynchronously on a background
thread when needed. This pattern is useful for keeping the data
displayed in a UI in sync with the data stored in a database.
Repository
Repository Cont’d
Repository Cont’d
Project Structure
Lab 1 – (Products App – MVC)
• Build an application that get a list of products from the following
JSON API
https://dummyjson.com/products

All Products Main Screen Favorite Products


Displays Products on a
list, and gives the user
the option to add any
of them to favorite.
From Favorite user can
delete any item.
Don’t Forget
Architecture: MVC
Network Lib: Retrofit
DB: Room
Observation: LiveData
Lab Milestones
Create Retrofit class that connects to products API and fetches data.

Create a Room database that inserts, deletes and retrieves products.

Create AllProducts Activity class that shows data from network and
add items to database

Create FavoriteProducts Activity class that shows and deletes data


from database

(Don’t forget to separate the logic from adapter)


Android MVC in Action
Applying MVC to Android
When the Controller updates the View, the View cannot update if it is merely
a static .xml layout.

Activity almost always contain some view logic, such as showing or hiding
views, displaying a progress bar, toast or updating the text on screen, in
response to user input.

If the Activity must hold references to views and logic for changing them as
well as all the logic for its Controller responsibilities, then the Activity
effectively serves as both the Controller and the View in this pattern
Applying MVC to Android
• The controller then has all the responsibility for what’s displayed on screen.
For a simple screen, this can be manageable but, as features get added,
this file will keep growing.

• Activities are tightly-coupled to both UI and data access mechanisms. Thus,


it is easy to fall into the trap of placing both controller and view logic in an
activity or fragment.

• It is difficult to test components when they are tightly-coupled. You should


test the code that exists in the controller. Much of the code under test will
end up needing to run Android SDK components, such as activities.
Applying MVC to Android
Having the Activity act as both the
Controller and the View is problematic .
1. It defeats the goal of
MVC, which was to
separate
responsibilities
2. Having the Activity as
the Controller in MVC
poses a problem for
unit testing.
Model View Presenter (MVP)
Introduction
The MVC architecture pattern theoretically allows an app to achieve
separation of concerns and unit testability, in practice, MVC didn’t
quite work on Android.

The problem was that the Android Activity, unfortunately, served the
role of both View and Controller.

Ideally, you would want to somehow move the Controller out of the
Activity into its own class so that the Controller can be unit testable.
MVP
One alternative to the problems presented by MVC is to decouple some of the parts
from each other.

MVP is an architecture pattern that you can use to deal with some of the
shortcomings of MVC, and is a good alternative architecture.

It provides an easy way to think about the structure of your app.


It provides modularity, testability and, more clean and maintainable codebase.
MVP Components
• Model: The model will continue to contain the data in simple classes,
so nothing changes here.

• View: The view will continue to be implemented using Activity or


Fragment classes, but we will change the scope of the view.

• Presenter: responsible to act as the man in the middle between View


and Model. It retrieves data from the Model and passes it formatted
to the View. But unlike the typical MVC, it also decides what happens
when you interact with the View.
View in MVP
• Responsible for displaying the UI

• With MVP, this role is specifically designated to an Activity or


Fragment.

• The View will:


1. Hide and display views
2. Handle navigating to other Activities through intents
Presenter in MVP
• It is the glue class that talks to both the Model and View.

• Any code that does not directly handle UI or other Android framework specific
logic should be moved out of the View and into the Presenter class.

• Model and Presenter do not extend Android framework-specific classes, and, for
the most part, they should not contain Android framework-specific classes to be
easily tested.

• Presenter’s job is to do any additional


mapping or formatting of the data before
handing it to the View to display it.
MVP flow
Unlike MVC, In MVP View (Activity–fragment)
serves as the entry point for user input and starts
to handle it.

By making View inform the Presenter of


the user input, and the Presenter can handle it
by updating the Model.

Once the Model has been


updated, the Presenter can then update the View
with the most up-to-date data.
MVP flow
2. Activity notify
presenter
1. Activity listens
for user inputs

4. Presenter then
updates the View 3. Presenter updates
the Model

Model and View do not need to be aware of


each other.
Presenter is Unit-test Ready
Presenter can now be unit tested. Because it does not extend any class
specific to the Android framework, the Presenter can be instantiated
through a constructor like
Presenter presenter = new Presenter();
Allowing us to call methods on an instance of the Presenter like
presenter.onDeleteTapped(movieToDelete) to test that
it behaves as expected in unit tests.
Presenter is Unit-test Ready
To achieve the “testable” requirement, Presenter should not contain
references to any Android framework-specific classes, such as:
• Context
• View
• Intent.

However, the Presenter, needs to talk to the View, which means it needs a
reference to the Activity, an Android framework specific class.
How can you work around to get a reference to an Android class when you
write your unit tests?
Presenter & View Referencing
The way to resolve this problem is to create interfaces for the Presenter
and View, keeping the interfaces as contracts between View and
presenter.

The Presenter class implements the PresenterInterface and the Activity


implements the ViewInterface
Presenter & View Contract
View Interface
View Implementation
View Implementation Cont’d
View Implementation Cont’d
Presenter Interface
Presenter Implementation
View Referencing from a Presenter
The Presenter class will then hold a reference to an instance of the
ViewInterface interface, rather than a reference directly to the Activity.

This way, the Presenter and View interact with each other through
interfaces rather than actual implementations, which is, in general, a
good software engineering principle that allows decoupling of the two
classes.

This allows you to mock the ViewInterface in the Presenter for unit
testing
MVP Advantages
By dividing an Activity into separate Model, View, and Presenter classes
with interfaces, you are able to :
• Achieve separation of concerns as well as
• Unit-testable Models and Presenters.

These were our first goals to architecture !


Guide to App Architecture
Recommended app architecture
In Android each application should have at least two layers:
• The UI layer that displays application data on the screen.
• The Data layer that contains the business logic of your app and exposes
application data.
• You can add an additional layer
called the Domain layer to simplify
and reuse the interactions
between the UI and data layers.
Read more..
Data Layer
Introduction to Data Layer
The data layer contains application data and business logic.

The business logic is what gives value to your app—it's made of real-
world business rules that determine how application data must be
created, stored, and changed.

• This separation of concerns allows the data layer to be used on


multiple screens, share information between different parts of the
app, and reproduce business logic outside of the UI for unit testing
Data Layer Components
• The data layer is made of repositories that each can contain
zero to many data sources.

• You should create a


repository class for
each different type of
data you handle in
your app.
Starting From The Ground Up
Data Sources
In your app you will work with different sources for data. For example:
local data source (i.e.: database) and remote data source (network)

Each data source class should have the responsibility of working with
only one source of data, which can be a file, a network source, or a
local database.

Data source classes are the bridge between the application and the
system for data operations.
Naming Convention
• Data source classes are named after the data they're responsible for
and the source they use. The convention is as follows:

Type of Data + Type of Source + DataSource.

Products Remote
Movies Local
etc.

Example: MoviesRemoteDataSource
Remote Data Source
Local Data Source
Local Data Source Implementation
Local Data Source Implementation
Local Data Source Implementation
Repository
Other layers in the hierarchy should never access data sources directly;
the entry points to the data layer are always the repository classes.

Repository classes are responsible for the following tasks:


• Exposing data to the rest of the app.
• Centralizing changes to the data.
• Resolving conflicts between multiple data sources.
• Abstracting sources of data from the rest of the app.
Naming Convention
Repository classes are named after the data that they're
responsible for. The convention is as follows:

Type of Data + Repository.


News
Products
Movies
Etc.
Example: MoviesRepository
Repository Implementation
Repository Implementation Cont’d
Repository Implementation Cont’d

And for this topic you can find more on: https://developer.android.com/jetpack/guide/data-layer
Folder Structure
Lab 1 – (Products App – MVP)
• Build an application that get a list of products from the following
JSON API
https://dummyjson.com/products

Main Screen Favorite Products


Displays Products on a All Products

list, and gives the user


the option to add any
of them to favorite.
From Favorite user can
delete any item.
Don’t Forget
Architecture: MVP
Network Lib: Retrofit
DB: Room
Observation: LiveData
Try to use Repository pattern
Lab Milestones
Create Retrofit part that connects to products API and fetches data.

Create a Room database that inserts, deletes and retrieves products.

Create a Repository that manages the Local and Remote data sources.

Create AllProducts Activity and AllProducts Presenter classes that


show data from network and add items to database

Create FavoriteProducts Activity and FavoriteProducts Presenter


classes that show and delete data from database
MVP in Action
MVP in Action
MVP served us well through the years. It is
1. Easy to follow design
2. Follows the separation of concern
3. Made unit testing pretty easy

And that were our main goal of the architectural patterns.

Unfortunately, it has some drawbacks which start to unfold as


more code and more logic gets involved in the MVP triad.
MVP Drawback
Tight-coupling between the View and the Presenter. Each View holds a
reference to the Presenter and each Presenter holds a reference to the
View.

Communication between view-presenter has to be opened via a


Contract. This approach results in less-generic code (since the
Presenter most of the time can’t be used as a layer in the MVP triad for
another View).

View and Presenter will rapidly expand in the code-line size.


Any Suggestions?
Model View ViewModel (MVVM)
Introduction
Model View ViewModel (MVVM) is an architectural pattern whose main
purpose is to achieve separation of concerns through a clear distinction
between the roles of each of its components:

View displays the UI and informs the other layers about user actions. i.e.:
fragments, activity..

Model retrieves information from your data source and exposes it to the
ViewModels. i.e.: POJO, Repository and data sources

ViewModel exposes information to the View.


View
The only component that the end user really interacts with ViewModel.

The View is responsible for:


1. Displaying the interface by observing ViewModel to obtain the
necessary information it needs and update the UI accordingly.
2. Informs ViewModel about user actions.

Views are usually represented in Android as Activities or Fragments.


Model
The Model is in charge of exposing relevant data to your ViewModels in
a way that is easy to consume.

It should also receive any events from the ViewModel that it needs to
create, read, update or delete any necessary data from the backend
(Model don’t change)

Model can be: POJO, Repository and different data sources.


ViewModel
A layer that provides information to Views. It is not interested in what
consumes it.
Views can request information from any ViewModel they need.

ViewModel is also responsible for exposing events that the Views can
observe. i.e.: New movie in your Database.

The ViewModel retrieves the necessary information from the Model, applies
the necessary operations and exposes any relevant data for the Views.
MVVM Flow
In MVVM View serves as the entry point for user
input and starts to handle it. VIEW

View consumes the proper methods or data


exposed by the viewModel(s) to handle user input.
ViewModel exposes data and methods without VIEW MODEL
caring whoever will consume/use it.

ViewModel communicates with the model to keep


both sides updated
MODEL
There is a strong emphasis that the ViewModel should
not contain any references to Views.
MVVM Flow

UI Events
Update

Data Update
VIEW Events ViewModel Notify Model
Data
Jetpack ViewModel
Configuration Change Problem
During configuration change in Android all data contained within
components is lost

The most common solution to this problem is to save your data in your
onSaveInstanceState()in the bundle and restore it later in your
onCreate()method.

This approach only works for primitive data such as integers or simple classes
that can be serialized and deserialized

What about complicated one?


Configuration Change Solution
Google has a special class to build your ViewModels
called ViewModel.

The ViewModel class is specially designed to manage


and store information in a lifecycleaware manner.
This means that the data stored inside it can survive
configuration/lifecycle changes like screen rotations.

The ViewModel remains in memory until the lifecycle


object to which it belongs has completely terminated.
Using ViewModel
When we declare ViewModel we don’t call the direct constructor instead we
call ViewModelProvider provided by Android to create ViewModels.

ViewModelProvider returns an existing ViewModel if one exists, or it creates


a new one if it does not already exist.

ViewModelProvider creates a ViewModel instance in association with the


given scope (an activity or a fragment).

The created ViewModel is retained as long as the scope is alive. For example,
if the scope is a fragment, the ViewModel is retained until the fragment is
detached.
How to ViewModel

1. Create a subclass of the ViewModel

2. Inside this subclass create the needed methods that communicate


model to update or expose the needed data.

3. In your UI create an instance of the created subClass


Demo
Movie App. to MVVM
How to ViewModel
1. Create a subclass of the ViewModel

2. Inside this subclass create the


needed methods that
communicate model to update
or expose the needed data.
How to ViewModel
3. To create a viewModel inside your UI (in our case the activity), use a
ViewModelProvider this way

val viewModel: ViewModelSubClass =


ViewModelProvider(ViewModelStoreOwner).get(ViewModelSubClass::class.java)

val viewModel : FavMoviesViewModel =


ViewModelProvider(this).get(FavMoviesViewModel::class.java)
How ViewModelProvider works
ViewModelProvider can only instantiate ViewModels with no argument
constructor.

The ViewModelProvider internally call for the direct constructor of


ViewModel

So when one or more arguments needed in the viewModel, then we need to


use a Factory that we can pass to ViewModelProvider to use when an
instance of ViewModel is required.

For our case we need to pass repository to the constructor of our viewModel
ViewModelFactory
The factory method pattern is a creational design pattern that uses
factory methods to create objects. A factory method is a method that
returns an instance of the same class.

A ViewModelFactory instantiates ViewModel objects, with or without


constructor parameters.
Factory
Using ViewModel Factory
To use a viewModelFactory inside UI
View – Kotlin
View – Cont’d
View – Cont’d
ViewModel
• Handle configuration changes: ViewModel objects are automatically retained
whenever activity is recreated due to configuration changes.

• Lifecycle Awareness: ViewModel objects are also lifecycle-aware. They are


automatically cleared when the Lifecycle they are observing gets permanently
destroyed.

• Data Sharing: Data can be easily shared between fragments in an activity using
ViewModels.

• Kotlin-Coroutines support: ViewModel includes support for Kotlin-Coroutines. So,


they can be easily integrated for any asynchronous processing.
MVVM Advantages
• In MVVM By handling all data manipulation to ViewModels, unit
testing becomes very easy since they don't have any reference to the
Views.

• MVVM solves the fat controller issue by providing a better separation


of concerns. Adding ViewModels, whose main purpose is to be
completely separated from the Views, reduces the risk of having too
much code in the otherlayers.
MVVM Drawbacks
• The main disadvantage of this architecture pattern is that it can be
considered complex for applications whose UI is rather simple.

Adding as much level of abstraction in such apps can result in boiler


plate code that only makes the underlying logic more complicated.
MVC MVP MVVM
Fragment Communication
Inter-fragment Communication
• Fragments should be loosely coupled.
• Don’t maintain direct reference of fragments within each other

Activity
Interface

Fragment_A_Sender Fragment_B_Reciever
Communicator Design Pattern
Communicator Interface

fun respond( . . .)

Fragment_A Activity_subClass Fragment_B

val ref : Communicator fun respond( . . .) fun changeData(..)


Communicator Design Pattern

Fragment_A MainActivity Fragment_B

Class Fragment_A : Fragment( ){ class MainActivity : Activity ( ) , class FragmentB : Fragment( ){


lateinit var comm: Communicator Communicator{ fun changeData(data: String){
fun respond(data: String) {
override fun onActivityCreated(b: Bundle){ val f2 = }}
comm = activity as Communicator manager.findFragmentById(R.id.f2) as
} FragmentB

fun onClick(v: View){ f2.changeData(data) } Interface Communicator{


comm.respond(“button was clicked”) } fun respond(data: String)
} } }
SharedViewModel
The second way we can implement fragment communication is via
ViewModels.

As known a view can consume one or more viewmodel. Also, the


viewModel can be consumed by more than one view.

A viewModel would make a good and easy solution for commnication


SharedViewModel
• ViewModel act as the
man in the middle. SharedViewModel

• Without any need for


Activity
interfaces or refrence
to fragments. They
use it freely to
get/set the required
data. Fragment_A Fragment_B
What we will do

Remember the
fragment counter lab?

Let’s try it using


ViewModel!
1. Create ViewModel
2. Create Static Fragment
3. Create Dynamic Fragment
4. MainActivity
SharedViewModel vs. SafeArgs.
While Navigation Components allow you to attach data to a navigation
operation by defining arguments for a destination.

Navigation Components move the data via the bundle which has a very small
size with limitations on the types of data that could be added, primitives,
serializables or parcelables.

In general, you should strongly prefer passing only the minimal amount of
data between destinations

If you need to pass large amounts of data, consider using a shared


ViewModel between your fragments.
Android KTX
• Android KTX is a set of Kotlin extensions that are included with Android Jetpack and
other Android libraries.

• KTX extensions provide concise, idiomatic Kotlin to Jetpack, Android platform, and
other APIs. To do so, these extensions leverage several Kotlin language features

• To start using anything in the Android KTX, add the following dependency to your
project's build.gradle file:
repositories {
google()
}

• In your module’s build.gradle add the needed dependency.


Android KTX – Cont’d
In the dependencies section we can add the required module. For example:
implementation "androidx.activity:activity-ktx:1.5.0"
implementation "androidx.fragment:fragment-ktx:1.6.2"

Hence, we can create our ViewModel using a simple way using the
by viewModels() which is an extension function makes the creation of a viewmodel easier

1. For viewModel with empty constructor use:


val myViewModel : MyViewModel by viewModels()

2. For prameterized constructor send your factory as a lambda argument to the viewModels()
val myViewModel : MyViewModel by viewModels { factoryInstance }
build.gradle Configuration Needed
Add Kotlin Annotation Processor Tool (kapt) to your plugins section
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
For Room& Coroutine add the following dependencies to your dependencies section
//Room
implementation "androidx.room:room-ktx:2.5.0"
implementation "androidx.room:room-runtime:2.5.0“
kapt "androidx.room:room-compiler:2.5.0“
//ViewModel & livedata
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0’
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1’
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
//Coroutine
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0‘
Lab 3 – (Products App – MVVM)
• Build an application that get a list of products from the following JSON API
https://dummyjson.com/products
And displays them on a list, and gives the user the option to add any of them
to favorite.
Hint: Main Screen Favorite Products
All Products
Architecture: MVVM
Network Lib: Retrofit
DB: Room
Observation: LiveData
Language: Kotlin
Use Coroutine.
Lab Milestones
Create Retrofit part that connects to products API and fetches data.

Create a Room database that inserts, deletes and retrieves products.

Create a Repository that manages the Local and Remote data sources.

Create AllProducts Activity and AllProducts ViewModel classes that


show data from network and add items to database

Create FavoriteProducts Activity and FavoriteProducts ViewModel


classes that show and delete data from database
Thank you!

You might also like