SlideShare a Scribd company logo
Architecture Components
Constantine Mars
Team Lead, Senior Developer @ DataArt
Построение современной архитектуры
мобильных приложений
Background
Software Architecture Basics
Components:
-Activities
-Fragments
-Services
-Content Providers
-Broadcast Receivers
Android Has “Good Bones”
App-hopping
OS may kill app at random time
App components lifecycle is not under control
Components should not depend on each other
Can’t rely on data, stored in components
There are Everyday Problems to Solve
Simply related to Activity Lifecycle
-Separation of concerns
-Provide solid user experience
-Keep UI lean and simple
-Keep UI free of app logic
-Drive UI from model
-Use persistent model
-Assign clear responsibilities for each model class
Common Principles for staying in mind :)
Image from fernandocejas.com
Separation of Concerns...
Image from fernandocejas.com
Clean Architecture
-Modular app
-Each class responsible for one well-defined function
-Should be no god objects
-The app should be testable
Remember Good Architecture Goals...
Android Recommended Architecture
Android Recommended Architecture. Another View
Be together. not the same
“It is impossible to have one way of writing apps that will be the best for
every scenario. That being said, this recommended architecture should be
a good starting point for most use cases. If you already have a good way
of writing Android apps, you don't need to change.”
Be together. not the same
Building blocks
Architecture Components
Purpose: Display data and pass on UI events
Neither contain the UI data, nor directly manipulate data
Examples: Activity, Fragment
Views = UI Controllers = LifecycleOwners
Lifecycle = states + events
Implement Lifecycle since Beta
AppCompatActivity, Fragment
ViewModel
Data holder for Activity/Fragment
Survives configuration changes
NEVER references View / Activity / Fragment
ViewModel
public class DetailActivityViewModel extends ViewModel {
private WeatherEntry mWeather;
public DetailActivityViewModel() {}
public WeatherEntry getWeather() { return mWeather; }
public void setWeather(WeatherEntry weatherEntry) { mWeather = weatherEntry; }
}
ViewModel and Lifecycle
ViewModel and LifecycleOwner
public class DetailActivity extends LifecycleActivity {
DetailActivityViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class);
}
...
Represent data needed for the UI to display
An observable data holder
Lifecycle aware
Automatic subscription management
LiveData
LiveData event propagation
LiveData sample implementation
Live Data
public class DetailActivityViewModel extends ViewModel {
private MutableLiveData<WeatherEntry> mWeather;
public DetailActivityViewModel() {}
public MutableLiveData<WeatherEntry> getWeather() {
return mWeather;
}
public void setWeather(WeatherEntry weatherEntry) {
mWeather.postValue(weatherEntry);
}
}
Live Data observing
public class DetailActivity extends LifecycleActivity {
DetailActivityViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class);
viewModel.getWeather().observe(this, weatherEntry -> {
if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); }
});
}
-Single source of truth
-ViewModels simply request data
from the repository
-Is a mediator between
the different data sources
Repository
Image from fernandocejas.com
Manages data from a remote data
source, such as the internet
May use REST, Cloud
Remote Network Data Source
Manages local data stored in the
database
Model
Each class in the diagram only
stores a reference to the class or
classes directly "below it" and not
any classes above it
Layered architecture pattern
ORM by Google
Room
-Less boilerplate compared to the built-in APIs
-Compile-time validation of SQL queries
-Data observation via LiveData, RxJava
Room ORM purposes
-@Entity
-@Dao
-@Database
Room annotations
Entity
@Entity declaration
@Entity(tableName = "weather",
indices = {@Index(value = {"date"}, unique = true)})
public class WeatherEntry {
@PrimaryKey(autoGenerate = true)
private int id;
…
}
@Entity constructors
//Room constructor
public WeatherEntry(int id, int weatherIconId, Date date, ...) {
//Json constructor - ignored by Room
@Ignore
public WeatherEntry(int weatherIconId, Date date,
// (!) Only one constructor should be exposed to Room
...
Dao
@Dao declaration
@Dao
public interface WeatherDao {
@Query("SELECT * FROM weather") List<WeatherEntry> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(WeatherEntry... weatherEntries);
@Delete void delete(WeatherEntry weatherEntry);
}
Database
@Database declaration
@Database(entities = {WeatherEntry.class}, version = 1)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {
public abstract WeatherDao weatherDao();
}
@Database - a singleton
private static final String DATABASE_NAME = "weather";
private static final Object LOCK = new Object();
private static volatile AppDatabase sInstance;
public static AppDatabase getInstance(Context context) {
if (sInstance == null) { synchronized (LOCK) {
if (sInstance == null) {
sInstance = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, AppDatabase.DATABASE_NAME).build();
}
}}
return sInstance;
}
Type converters
class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
Alternatives
Repository
Repository pattern
public class WeatherRepository {
public synchronized static WeatherRepository getInstance();
public synchronized void initializeData();
private void deleteOldData();
private boolean isFetchNeeded();
private void startFetchWeatherService();
}
Repository - fetch data from network
mWeatherNetworkDataSource = weatherNetworkDataSource;
LiveData<WeatherEntry[]> networkData = mWeatherNetworkDataSource.getCurrentWeatherForecasts();
networkData.observeForever(newForecastsFromNetwork -> {
mExecutors.diskIO().execute(() -> {
mWeatherDao.bulkInsert(newForecastsFromNetwork);
Log.d(LOG_TAG, "New values inserted");
});
});
Repository - use LiveData
private WeatherNetworkDataSource(Context context, AppExecutors executors) {
mContext = context;
mExecutors = executors;
mDownloadedWeatherForecasts = new MutableLiveData<WeatherEntry[]>();
}
Check when to fetch
private boolean isFetchNeeded() {
Date today = CustomDateUtils.getNormalizedUtcDateForToday();
int count = mWeatherDao.countAllFutureWeather(today);
return (count < WeatherNetworkDataSource.NUM_DAYS);
}
Check when to fetch
public synchronized void initializeData() {
if (mInitialized) return;
mInitialized = true;
mExecutors.diskIO().execute(() -> {
if (isFetchNeeded()) {
startFetchWeatherService();
}
});
}
And again - observe LiveData
public class DetailActivity extends LifecycleActivity {
DetailActivityViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class);
viewModel.getWeather().observe(this, weatherEntry -> {
if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); }
});
}
The whole picture for sample project
Paging Library
Paging Library flow
Data source
KeyedDataSource - if you need to use data from item N to fetch item N+1.
TiledDataSource - if you need to fetch pages in range of data from any location you choose in your data store
DAO for KeyedDataSource
@Dao
interface UserDao {
@Query("SELECT * from user ORDER BY name DESC LIMIT :limit")
public abstract List<User> userNameInitial(int limit);
@Query("SELECT * from user WHERE name < :key ORDER BY name DESC LIMIT :limit")
public abstract List<User> userNameLoadAfter(String key, int limit);
@Query("SELECT * from user WHERE name > :key ORDER BY name ASC LIMIT :limit")
public abstract List<User> userNameLoadBefore(String key, int limit);
}
KeyedDataSource implementation
public class KeyedUserQueryDataSource extends KeyedDataSource<String, User> {
@Override public boolean isInvalid() { return super.isInvalid(); }
@Override public String getKey(@NonNull User item) { return item.getName(); }
@Override public List<User> loadInitial(int pageSize) {
return mUserDao.userNameInitial(pageSize); }
@Override public List<User> loadBefore(@NonNull String userName, int pageSize) {
return mUserDao.userNameLoadBefore(userName, pageSize); }
@Override public List<User> loadAfter(@Nullable String userName, int pageSize) {
return mUserDao.userNameLoadAfter(userName, pageSize); }
}
TiledDataSource implementation
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY mAge DESC")
public abstract TiledDataSource<User> loadUsersByAgeDesc();
}
TiledDataSource - under the hood
@Dao
interface UserDao {
@Query("SELECT COUNT(*) from user")
public abstract Integer getUserCount();
@Query("SELECT * from user ORDER BY mName DESC LIMIT :limit OFFSET :offset")
public abstract List<User> userNameLimitOffset(int limit, int offset);
}
TiledDataSource - under the hood
public class OffsetUserQueryDataSource extends TiledDataSource<User> {
@Override public boolean isInvalid() { return super.isInvalid(); }
@Override public int countItems() { return mUserDao.getUserCount(); }
@Override public List<User> loadRange(int startPosition, int loadCount) {
return mUserDao.userNameLimitOffset(loadCount, startPosition);
}
}
Paging Library - PagedList
DataSource
PagedList - loads its data in chunks (pages) from a DataSource
PagedListAdapter
LivePagedListProvider
Paging Library - LivePagedListProvider
DataSource
PagedList
PagedListAdapter - listens to PagedList loading callbacks as pages are loaded, and uses DiffUtil on a
background thread to compute fine grained updates as new PagedLists are received.
LivePagedListProvider - provides a LiveData<PagedList>, given a
means to construct a DataSource
LivePagedListProvider generation by DAO
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY lastName ASC")
public abstract LivePagedListProvider<Integer, User> usersByLastName();
}
Paging Library - PagedListAdapter
DataSource
PagedList
PagedListAdapter - listens to PagedList loading callbacks as pages are
loaded, and uses DiffUtil on a background thread to compute fine grained
updates as new PagedLists are received.
LivePagedListProvider
PagedListAdapter usage pattern - DAO
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY lastName ASC")
public abstract LivePagedListProvider<Integer, User> usersByLastName();
}
PagedListAdapter usage pattern -
PagedList.Config
class MyViewModel extends ViewModel {
public final LiveData<PagedList<User>> usersList;
public MyViewModel(UserDao userDao) {
usersList = userDao.usersByLastName().create(
/* initial load position */ 0,
new PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(50)
.build());
}
}
PagedListAdapter usage pattern - binding
class MyActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
RecyclerView recyclerView = findViewById(R.id.user_list);
UserAdapter<User> adapter = new UserAdapter();
viewModel.usersList.observe(this, pagedList -> adapter.setList(pagedList));
recyclerView.setAdapter(adapter);
}
}
PagedListAdapter implementation
class UserAdapter extends PagedListAdapter<User, UserViewHolder> {
public UserAdapter() { super(DIFF_CALLBACK); }
@Override public void onBindViewHolder(UserViewHolder holder, int position) {
User user = getItem(position);
if (user != null) { holder.bindTo(user);
} else { holder.clear(); }
}
...
PagedListAdapter implementation
class UserAdapter extends PagedListAdapter<User, UserViewHolder> {
...
public static final DiffCallback<User> DIFF_CALLBACK = new DiffCallback<User>() {
@Override public boolean areItemsTheSame( @NonNull User oldUser, @NonNull User
newUser) { return oldUser.getId() == newUser.getId(); }
@Override public boolean areContentsTheSame( @NonNull User oldUser, @NonNull User
newUser) { return oldUser.equals(newUser); }
}
}
Paging Library flow
Testing
Sneak peek :)
UI Controller - Instrumentation
ViewModel - JUnit
Repository - JUnit, MockWebServer
Scalability and advices
Almost there...
What if...
I use RxJava?
I already have MVP?
I love Kotlin?
I’m working on legacy project?
Typical questions
The Answer is...
Read, watch and visit...
Links
Guide to App Architecture https://developer.android.com/topic/libraries/architecture/guide.html
Architecture Components
https://developer.android.com/topic/libraries/architecture/index.html
I/O ‘17 Architecture Components Introduction - https://youtu.be/FrteWKKVyzI
Solving the Lifecycle Problem - https://youtu.be/bEKNi1JOrNs
Persistence and Offline - https://youtu.be/MfHsPGQ6bgE
Architecture Components on GDD Europe - https://youtu.be/Ts-uxYiBEQ8
GDD Europe CodeLabs g.co/codelabs/gdd17
Google Github samples https://github.com/googlesamples/android-architecture-components
What to read and watch :)
Android MVP Helper https://github.com/Ufkoku/AndroidMVPHelper
Moxy https://github.com/Arello-Mobile/Moxy
Mosby https://github.com/sockeqwe/mosby
Clean Architecture https://github.com/android10/Android-CleanArchitecture
Reark https://github.com/reark/reark
MVP + Dagger2 + Rx https://android.jlelse.eu/mvp-dagger-2-rx-clean-modern-android-app-code-74f63c9a6f2f
Architecture the Lost Years by Uncle Bob https://youtu.be/WpkDN78P884
Alternatives to consider
Where to go :)
Thank you! :)
Constantine Mars
@ConstantineMars
+ConstantineMars
Mobile Architecture Club

More Related Content

What's hot

Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Kevin Octavian
 
JQuery New Evolution
JQuery New EvolutionJQuery New Evolution
JQuery New EvolutionAllan Huang
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
Ignacio Coloma
 
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Android Jetpack: ViewModel and Testing
Android Jetpack: ViewModel and TestingAndroid Jetpack: ViewModel and Testing
Android Jetpack: ViewModel and Testing
Yongjun Kim
 
Android Architecture - Khoa Tran
Android Architecture -  Khoa TranAndroid Architecture -  Khoa Tran
Android Architecture - Khoa Tran
Tu Le Dinh
 
State management in android applications
State management in android applicationsState management in android applications
State management in android applications
Gabor Varadi
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
Knoldus Inc.
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Ryosuke Uchitate
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
Vitebsk Miniq
 
Android sq lite-chapter 22
Android sq lite-chapter 22Android sq lite-chapter 22
Android sq lite-chapter 22
Dr. Ramkumar Lakshminarayanan
 
Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)
Gabor Varadi
 
Paging Like A Pro
Paging Like A ProPaging Like A Pro
Paging Like A Pro
Gabor Varadi
 
Client Server Communication on iOS
Client Server Communication on iOSClient Server Communication on iOS
Client Server Communication on iOS
Make School
 
Simple Jdbc With Spring 2.5
Simple Jdbc With Spring 2.5Simple Jdbc With Spring 2.5
Simple Jdbc With Spring 2.5
David Motta Baldarrago
 
Wicket Security Presentation
Wicket Security PresentationWicket Security Presentation
Wicket Security Presentation
mrmean
 
บทที่3
บทที่3บทที่3
บทที่3Palm Unnop
 
Working effectively with ViewModels and TDD - UA Mobile 2019
Working effectively with ViewModels and TDD - UA Mobile 2019Working effectively with ViewModels and TDD - UA Mobile 2019
Working effectively with ViewModels and TDD - UA Mobile 2019
UA Mobile
 

What's hot (20)

Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1
 
JQuery New Evolution
JQuery New EvolutionJQuery New Evolution
JQuery New Evolution
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
 
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
 
Android Jetpack: ViewModel and Testing
Android Jetpack: ViewModel and TestingAndroid Jetpack: ViewModel and Testing
Android Jetpack: ViewModel and Testing
 
Android Architecture - Khoa Tran
Android Architecture -  Khoa TranAndroid Architecture -  Khoa Tran
Android Architecture - Khoa Tran
 
State management in android applications
State management in android applicationsState management in android applications
State management in android applications
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
 
Android sq lite-chapter 22
Android sq lite-chapter 22Android sq lite-chapter 22
Android sq lite-chapter 22
 
spring-tutorial
spring-tutorialspring-tutorial
spring-tutorial
 
Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)
 
Paging Like A Pro
Paging Like A ProPaging Like A Pro
Paging Like A Pro
 
Client Server Communication on iOS
Client Server Communication on iOSClient Server Communication on iOS
Client Server Communication on iOS
 
Lecture17
Lecture17Lecture17
Lecture17
 
Simple Jdbc With Spring 2.5
Simple Jdbc With Spring 2.5Simple Jdbc With Spring 2.5
Simple Jdbc With Spring 2.5
 
Wicket Security Presentation
Wicket Security PresentationWicket Security Presentation
Wicket Security Presentation
 
บทที่3
บทที่3บทที่3
บทที่3
 
Working effectively with ViewModels and TDD - UA Mobile 2019
Working effectively with ViewModels and TDD - UA Mobile 2019Working effectively with ViewModels and TDD - UA Mobile 2019
Working effectively with ViewModels and TDD - UA Mobile 2019
 

Similar to Architecture Components

Android Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, VonageAndroid Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, Vonage
DroidConTLV
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
Ahmad Arif Faizin
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
Hassan Abid
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureC.T.Co
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureAlexey Buzdin
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
DataArt
 
Presentation Android Architecture Components
Presentation Android Architecture ComponentsPresentation Android Architecture Components
Presentation Android Architecture Components
Attract Group
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
Pedro Vicente
 
Storage Plug-ins
Storage Plug-ins Storage Plug-ins
Storage Plug-ins buildacloud
 
Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta Indonesia
Pratama Nur Wijaya
 
Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"
Fwdays
 
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArtArchitecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Alina Vilk
 
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
Inhacking
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no android
Rodrigo de Souza Castro
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + Spring
Bryan Hsueh
 
"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин
Fwdays
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
Jose Manuel Pereira Garcia
 
My way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca editionMy way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca edition
Christian Panadero
 

Similar to Architecture Components (20)

Android Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, VonageAndroid Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, Vonage
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
 
Presentation Android Architecture Components
Presentation Android Architecture ComponentsPresentation Android Architecture Components
Presentation Android Architecture Components
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
 
Storage Plug-ins
Storage Plug-ins Storage Plug-ins
Storage Plug-ins
 
Androidppt 1
Androidppt 1Androidppt 1
Androidppt 1
 
Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta Indonesia
 
Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"
 
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArtArchitecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
 
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no android
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + Spring
 
"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
My way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca editionMy way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca edition
 

More from DataArt

DataArt Custom Software Engineering with a Human Approach
DataArt Custom Software Engineering with a Human ApproachDataArt Custom Software Engineering with a Human Approach
DataArt Custom Software Engineering with a Human Approach
DataArt
 
DataArt Healthcare & Life Sciences
DataArt Healthcare & Life SciencesDataArt Healthcare & Life Sciences
DataArt Healthcare & Life Sciences
DataArt
 
DataArt Financial Services and Capital Markets
DataArt Financial Services and Capital MarketsDataArt Financial Services and Capital Markets
DataArt Financial Services and Capital Markets
DataArt
 
About DataArt HR Partners
About DataArt HR PartnersAbout DataArt HR Partners
About DataArt HR Partners
DataArt
 
Event management в IT
Event management в ITEvent management в IT
Event management в IT
DataArt
 
Digital Marketing from inside
Digital Marketing from insideDigital Marketing from inside
Digital Marketing from inside
DataArt
 
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
What's new in Android, Igor Malytsky ( Google Post I|O Tour)What's new in Android, Igor Malytsky ( Google Post I|O Tour)
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
DataArt
 
DevOps Workshop:Что бывает, когда DevOps приходит на проект
DevOps Workshop:Что бывает, когда DevOps приходит на проектDevOps Workshop:Что бывает, когда DevOps приходит на проект
DevOps Workshop:Что бывает, когда DevOps приходит на проект
DataArt
 
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArtIT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
DataArt
 
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
 «Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han... «Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
DataArt
 
Communication in QA's life
Communication in QA's lifeCommunication in QA's life
Communication in QA's life
DataArt
 
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
Нельзя просто так взять и договориться, или как мы работали со сложными людьмиНельзя просто так взять и договориться, или как мы работали со сложными людьми
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
DataArt
 
Знакомьтесь, DevOps
Знакомьтесь, DevOpsЗнакомьтесь, DevOps
Знакомьтесь, DevOps
DataArt
 
DevOps in real life
DevOps in real lifeDevOps in real life
DevOps in real life
DataArt
 
Codeless: автоматизация тестирования
Codeless: автоматизация тестированияCodeless: автоматизация тестирования
Codeless: автоматизация тестирования
DataArt
 
Selenoid
SelenoidSelenoid
Selenoid
DataArt
 
Selenide
SelenideSelenide
Selenide
DataArt
 
A. Sirota "Building an Automation Solution based on Appium"
A. Sirota "Building an Automation Solution based on Appium"A. Sirota "Building an Automation Solution based on Appium"
A. Sirota "Building an Automation Solution based on Appium"
DataArt
 
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
DataArt
 
IT talk: Как я перестал бояться и полюбил TestNG
IT talk: Как я перестал бояться и полюбил TestNGIT talk: Как я перестал бояться и полюбил TestNG
IT talk: Как я перестал бояться и полюбил TestNG
DataArt
 

More from DataArt (20)

DataArt Custom Software Engineering with a Human Approach
DataArt Custom Software Engineering with a Human ApproachDataArt Custom Software Engineering with a Human Approach
DataArt Custom Software Engineering with a Human Approach
 
DataArt Healthcare & Life Sciences
DataArt Healthcare & Life SciencesDataArt Healthcare & Life Sciences
DataArt Healthcare & Life Sciences
 
DataArt Financial Services and Capital Markets
DataArt Financial Services and Capital MarketsDataArt Financial Services and Capital Markets
DataArt Financial Services and Capital Markets
 
About DataArt HR Partners
About DataArt HR PartnersAbout DataArt HR Partners
About DataArt HR Partners
 
Event management в IT
Event management в ITEvent management в IT
Event management в IT
 
Digital Marketing from inside
Digital Marketing from insideDigital Marketing from inside
Digital Marketing from inside
 
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
What's new in Android, Igor Malytsky ( Google Post I|O Tour)What's new in Android, Igor Malytsky ( Google Post I|O Tour)
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
 
DevOps Workshop:Что бывает, когда DevOps приходит на проект
DevOps Workshop:Что бывает, когда DevOps приходит на проектDevOps Workshop:Что бывает, когда DevOps приходит на проект
DevOps Workshop:Что бывает, когда DevOps приходит на проект
 
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArtIT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
 
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
 «Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han... «Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
 
Communication in QA's life
Communication in QA's lifeCommunication in QA's life
Communication in QA's life
 
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
Нельзя просто так взять и договориться, или как мы работали со сложными людьмиНельзя просто так взять и договориться, или как мы работали со сложными людьми
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
 
Знакомьтесь, DevOps
Знакомьтесь, DevOpsЗнакомьтесь, DevOps
Знакомьтесь, DevOps
 
DevOps in real life
DevOps in real lifeDevOps in real life
DevOps in real life
 
Codeless: автоматизация тестирования
Codeless: автоматизация тестированияCodeless: автоматизация тестирования
Codeless: автоматизация тестирования
 
Selenoid
SelenoidSelenoid
Selenoid
 
Selenide
SelenideSelenide
Selenide
 
A. Sirota "Building an Automation Solution based on Appium"
A. Sirota "Building an Automation Solution based on Appium"A. Sirota "Building an Automation Solution based on Appium"
A. Sirota "Building an Automation Solution based on Appium"
 
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
 
IT talk: Как я перестал бояться и полюбил TestNG
IT talk: Как я перестал бояться и полюбил TestNGIT talk: Как я перестал бояться и полюбил TestNG
IT talk: Как я перестал бояться и полюбил TestNG
 

Recently uploaded

FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 

Recently uploaded (20)

FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 

Architecture Components

  • 1. Architecture Components Constantine Mars Team Lead, Senior Developer @ DataArt Построение современной архитектуры мобильных приложений
  • 4. App-hopping OS may kill app at random time App components lifecycle is not under control Components should not depend on each other Can’t rely on data, stored in components There are Everyday Problems to Solve
  • 5. Simply related to Activity Lifecycle
  • 6. -Separation of concerns -Provide solid user experience -Keep UI lean and simple -Keep UI free of app logic -Drive UI from model -Use persistent model -Assign clear responsibilities for each model class Common Principles for staying in mind :)
  • 9. -Modular app -Each class responsible for one well-defined function -Should be no god objects -The app should be testable Remember Good Architecture Goals...
  • 12. Be together. not the same
  • 13. “It is impossible to have one way of writing apps that will be the best for every scenario. That being said, this recommended architecture should be a good starting point for most use cases. If you already have a good way of writing Android apps, you don't need to change.” Be together. not the same
  • 15. Purpose: Display data and pass on UI events Neither contain the UI data, nor directly manipulate data Examples: Activity, Fragment Views = UI Controllers = LifecycleOwners
  • 16. Lifecycle = states + events
  • 17. Implement Lifecycle since Beta AppCompatActivity, Fragment
  • 18. ViewModel Data holder for Activity/Fragment Survives configuration changes NEVER references View / Activity / Fragment
  • 19. ViewModel public class DetailActivityViewModel extends ViewModel { private WeatherEntry mWeather; public DetailActivityViewModel() {} public WeatherEntry getWeather() { return mWeather; } public void setWeather(WeatherEntry weatherEntry) { mWeather = weatherEntry; } }
  • 21. ViewModel and LifecycleOwner public class DetailActivity extends LifecycleActivity { DetailActivityViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); } ...
  • 22. Represent data needed for the UI to display An observable data holder Lifecycle aware Automatic subscription management LiveData
  • 25. Live Data public class DetailActivityViewModel extends ViewModel { private MutableLiveData<WeatherEntry> mWeather; public DetailActivityViewModel() {} public MutableLiveData<WeatherEntry> getWeather() { return mWeather; } public void setWeather(WeatherEntry weatherEntry) { mWeather.postValue(weatherEntry); } }
  • 26. Live Data observing public class DetailActivity extends LifecycleActivity { DetailActivityViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); viewModel.getWeather().observe(this, weatherEntry -> { if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); } }); }
  • 27. -Single source of truth -ViewModels simply request data from the repository -Is a mediator between the different data sources Repository Image from fernandocejas.com
  • 28. Manages data from a remote data source, such as the internet May use REST, Cloud Remote Network Data Source
  • 29. Manages local data stored in the database Model
  • 30. Each class in the diagram only stores a reference to the class or classes directly "below it" and not any classes above it Layered architecture pattern
  • 32. -Less boilerplate compared to the built-in APIs -Compile-time validation of SQL queries -Data observation via LiveData, RxJava Room ORM purposes
  • 35. @Entity declaration @Entity(tableName = "weather", indices = {@Index(value = {"date"}, unique = true)}) public class WeatherEntry { @PrimaryKey(autoGenerate = true) private int id; … }
  • 36. @Entity constructors //Room constructor public WeatherEntry(int id, int weatherIconId, Date date, ...) { //Json constructor - ignored by Room @Ignore public WeatherEntry(int weatherIconId, Date date, // (!) Only one constructor should be exposed to Room ...
  • 37. Dao
  • 38. @Dao declaration @Dao public interface WeatherDao { @Query("SELECT * FROM weather") List<WeatherEntry> getAll(); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(WeatherEntry... weatherEntries); @Delete void delete(WeatherEntry weatherEntry); }
  • 40. @Database declaration @Database(entities = {WeatherEntry.class}, version = 1) @TypeConverters(DateConverter.class) public abstract class AppDatabase extends RoomDatabase { public abstract WeatherDao weatherDao(); }
  • 41. @Database - a singleton private static final String DATABASE_NAME = "weather"; private static final Object LOCK = new Object(); private static volatile AppDatabase sInstance; public static AppDatabase getInstance(Context context) { if (sInstance == null) { synchronized (LOCK) { if (sInstance == null) { sInstance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, AppDatabase.DATABASE_NAME).build(); } }} return sInstance; }
  • 42. Type converters class DateConverter { @TypeConverter public static Date toDate(Long timestamp) { return timestamp == null ? null : new Date(timestamp); } @TypeConverter public static Long toTimestamp(Date date) { return date == null ? null : date.getTime(); } }
  • 45. Repository pattern public class WeatherRepository { public synchronized static WeatherRepository getInstance(); public synchronized void initializeData(); private void deleteOldData(); private boolean isFetchNeeded(); private void startFetchWeatherService(); }
  • 46. Repository - fetch data from network mWeatherNetworkDataSource = weatherNetworkDataSource; LiveData<WeatherEntry[]> networkData = mWeatherNetworkDataSource.getCurrentWeatherForecasts(); networkData.observeForever(newForecastsFromNetwork -> { mExecutors.diskIO().execute(() -> { mWeatherDao.bulkInsert(newForecastsFromNetwork); Log.d(LOG_TAG, "New values inserted"); }); });
  • 47. Repository - use LiveData private WeatherNetworkDataSource(Context context, AppExecutors executors) { mContext = context; mExecutors = executors; mDownloadedWeatherForecasts = new MutableLiveData<WeatherEntry[]>(); }
  • 48. Check when to fetch private boolean isFetchNeeded() { Date today = CustomDateUtils.getNormalizedUtcDateForToday(); int count = mWeatherDao.countAllFutureWeather(today); return (count < WeatherNetworkDataSource.NUM_DAYS); }
  • 49. Check when to fetch public synchronized void initializeData() { if (mInitialized) return; mInitialized = true; mExecutors.diskIO().execute(() -> { if (isFetchNeeded()) { startFetchWeatherService(); } }); }
  • 50. And again - observe LiveData public class DetailActivity extends LifecycleActivity { DetailActivityViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); viewModel.getWeather().observe(this, weatherEntry -> { if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); } }); }
  • 51. The whole picture for sample project
  • 54. Data source KeyedDataSource - if you need to use data from item N to fetch item N+1. TiledDataSource - if you need to fetch pages in range of data from any location you choose in your data store
  • 55. DAO for KeyedDataSource @Dao interface UserDao { @Query("SELECT * from user ORDER BY name DESC LIMIT :limit") public abstract List<User> userNameInitial(int limit); @Query("SELECT * from user WHERE name < :key ORDER BY name DESC LIMIT :limit") public abstract List<User> userNameLoadAfter(String key, int limit); @Query("SELECT * from user WHERE name > :key ORDER BY name ASC LIMIT :limit") public abstract List<User> userNameLoadBefore(String key, int limit); }
  • 56. KeyedDataSource implementation public class KeyedUserQueryDataSource extends KeyedDataSource<String, User> { @Override public boolean isInvalid() { return super.isInvalid(); } @Override public String getKey(@NonNull User item) { return item.getName(); } @Override public List<User> loadInitial(int pageSize) { return mUserDao.userNameInitial(pageSize); } @Override public List<User> loadBefore(@NonNull String userName, int pageSize) { return mUserDao.userNameLoadBefore(userName, pageSize); } @Override public List<User> loadAfter(@Nullable String userName, int pageSize) { return mUserDao.userNameLoadAfter(userName, pageSize); } }
  • 57. TiledDataSource implementation @Dao interface UserDao { @Query("SELECT * FROM user ORDER BY mAge DESC") public abstract TiledDataSource<User> loadUsersByAgeDesc(); }
  • 58. TiledDataSource - under the hood @Dao interface UserDao { @Query("SELECT COUNT(*) from user") public abstract Integer getUserCount(); @Query("SELECT * from user ORDER BY mName DESC LIMIT :limit OFFSET :offset") public abstract List<User> userNameLimitOffset(int limit, int offset); }
  • 59. TiledDataSource - under the hood public class OffsetUserQueryDataSource extends TiledDataSource<User> { @Override public boolean isInvalid() { return super.isInvalid(); } @Override public int countItems() { return mUserDao.getUserCount(); } @Override public List<User> loadRange(int startPosition, int loadCount) { return mUserDao.userNameLimitOffset(loadCount, startPosition); } }
  • 60. Paging Library - PagedList DataSource PagedList - loads its data in chunks (pages) from a DataSource PagedListAdapter LivePagedListProvider
  • 61. Paging Library - LivePagedListProvider DataSource PagedList PagedListAdapter - listens to PagedList loading callbacks as pages are loaded, and uses DiffUtil on a background thread to compute fine grained updates as new PagedLists are received. LivePagedListProvider - provides a LiveData<PagedList>, given a means to construct a DataSource
  • 62. LivePagedListProvider generation by DAO @Dao interface UserDao { @Query("SELECT * FROM user ORDER BY lastName ASC") public abstract LivePagedListProvider<Integer, User> usersByLastName(); }
  • 63. Paging Library - PagedListAdapter DataSource PagedList PagedListAdapter - listens to PagedList loading callbacks as pages are loaded, and uses DiffUtil on a background thread to compute fine grained updates as new PagedLists are received. LivePagedListProvider
  • 64. PagedListAdapter usage pattern - DAO @Dao interface UserDao { @Query("SELECT * FROM user ORDER BY lastName ASC") public abstract LivePagedListProvider<Integer, User> usersByLastName(); }
  • 65. PagedListAdapter usage pattern - PagedList.Config class MyViewModel extends ViewModel { public final LiveData<PagedList<User>> usersList; public MyViewModel(UserDao userDao) { usersList = userDao.usersByLastName().create( /* initial load position */ 0, new PagedList.Config.Builder() .setPageSize(50) .setPrefetchDistance(50) .build()); } }
  • 66. PagedListAdapter usage pattern - binding class MyActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedState) { super.onCreate(savedState); MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class); RecyclerView recyclerView = findViewById(R.id.user_list); UserAdapter<User> adapter = new UserAdapter(); viewModel.usersList.observe(this, pagedList -> adapter.setList(pagedList)); recyclerView.setAdapter(adapter); } }
  • 67. PagedListAdapter implementation class UserAdapter extends PagedListAdapter<User, UserViewHolder> { public UserAdapter() { super(DIFF_CALLBACK); } @Override public void onBindViewHolder(UserViewHolder holder, int position) { User user = getItem(position); if (user != null) { holder.bindTo(user); } else { holder.clear(); } } ...
  • 68. PagedListAdapter implementation class UserAdapter extends PagedListAdapter<User, UserViewHolder> { ... public static final DiffCallback<User> DIFF_CALLBACK = new DiffCallback<User>() { @Override public boolean areItemsTheSame( @NonNull User oldUser, @NonNull User newUser) { return oldUser.getId() == newUser.getId(); } @Override public boolean areContentsTheSame( @NonNull User oldUser, @NonNull User newUser) { return oldUser.equals(newUser); } } }
  • 71. UI Controller - Instrumentation
  • 73. Repository - JUnit, MockWebServer
  • 75. What if... I use RxJava? I already have MVP? I love Kotlin? I’m working on legacy project? Typical questions
  • 77. Read, watch and visit... Links
  • 78. Guide to App Architecture https://developer.android.com/topic/libraries/architecture/guide.html Architecture Components https://developer.android.com/topic/libraries/architecture/index.html I/O ‘17 Architecture Components Introduction - https://youtu.be/FrteWKKVyzI Solving the Lifecycle Problem - https://youtu.be/bEKNi1JOrNs Persistence and Offline - https://youtu.be/MfHsPGQ6bgE Architecture Components on GDD Europe - https://youtu.be/Ts-uxYiBEQ8 GDD Europe CodeLabs g.co/codelabs/gdd17 Google Github samples https://github.com/googlesamples/android-architecture-components What to read and watch :)
  • 79. Android MVP Helper https://github.com/Ufkoku/AndroidMVPHelper Moxy https://github.com/Arello-Mobile/Moxy Mosby https://github.com/sockeqwe/mosby Clean Architecture https://github.com/android10/Android-CleanArchitecture Reark https://github.com/reark/reark MVP + Dagger2 + Rx https://android.jlelse.eu/mvp-dagger-2-rx-clean-modern-android-app-code-74f63c9a6f2f Architecture the Lost Years by Uncle Bob https://youtu.be/WpkDN78P884 Alternatives to consider
  • 81. Thank you! :) Constantine Mars @ConstantineMars +ConstantineMars Mobile Architecture Club