Advanced android app development

Advanced Android
App Development
Rachmat Wahyu Pramono
@rwpramono
rwpramono@gmail.com
“I fear not the man who has practiced
10,000 kicks once, but I fear the man
who has practiced one kick 10,000
times.”
Study Group != College Lecture
Course and Schedule
● Udacity Advanced Course
○ https://www.udacity.com/courses/ud855
○ Course Review
○ Project Review
● Additional Course
○ Android Optimization
○ Android Studio Productivity Boost
○ Android Architecture Component
Course and Schedule
Day 1
● Fragment
● Libraries
Day 2
● Firebase Cloud Messaging
● Places
Day 3
● Media Playback
● Widget
Day 4
● Espresso
● Publishing Your
App
Assessment
● 50% Attendance (10%)
● Student progress (15%)
○ 100% View on Udacity Course
○ Understanding, Activeness, Contribution
● Final projects (75%)
Example - Screenshot Dashboard
MUST BE
100% VIEWED
Final Project
● Original work
● Past project is fine
● Sky's the limit
● Containing 2 or more course material
● APK and Documentation / Source code
● Sent to rwpramono@gmail.com
● Due Date is 2 week after last meeting
Fragment & Libraries
Have anything to discuss ?
"A small leak
will sink a great
ship"
Memory Leak
Memory Leak
● Every app needs memory as a resource to do its work
● Android runtime triggers Garbage Collection (GC) when memory runs
short to reclaim memory by cleaning up objects that are no longer
useful
● What if the object is not used anymore in the program but its memory
cannot be released by the Garbage Collector ?
Memory Leak
● Memory leak causing more frequent GC events
● GC events makes rendering of UI and processing of events will stop
● Potentially more than 16ms drawing window
Memory Leak Effects
● No response to an input event (such as key press or screen touch
events) within 5 seconds
● A BroadcastReceiver hasn't finished executing within 10 seconds
● The system will eventually refuse to allocate more memory for your
app
Android Not Responding (ANR)
Unregistered listeners
public class LeaksActivity extends Activity implements LocationListener {
private LocationManager locationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaks);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
TimeUnit.MINUTES.toMillis(5), 100, this);
}
// Listener implementation omitted
}
Unregistered listeners
● Unregister the listener in onDestroy() method
@Override
protected void onDestroy() {
locationManager.removeUpdates(this);
super.onDestroy();
}
Inner classes
public class AsyncActivity extends Activity {
.
.
@Override
protected void onCreate(Bundle savedInstanceState) {
.
.
new BackgroundTask().execute();
}
private class BackgroundTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
}
}
Inner classes
● Avoid non-static inner classes
private static class BackgroundTask extends AsyncTask<Void, Void, String> {
.
.
}
● Use WeakReference if needed
public BackgroundTask(TextView resultTextView) {
this.textViewReference = new WeakReference<>(resultTextView);
}
Anonymous classes
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
. . . . .
mLeakyHandler.sendEmptyMessageDelayed(MESSAGE_ID,20000);
}
Anonymous classes
● Use static Handler class
@Override
protected void onDestroy() {
mLeakyHandler.removeMessages(MESSAGE_ID);
super.onDestroy();
}
Static Context and View object
public class MyActivity extends AppCompatActivity {
private static Context sContext;
. . . . .
}
Static Context and View object
● Avoid static to Android components like context, activities,
services and views
● Use WeakReference if needed
● Use Application context instead of the Activity context
● Set null in onDestroy() callback
Leak Canary
● Created by Pierre-Yves Ricau (Square Inc)
● Very easy to use
● Tracks objects for memory leaks
Udacity Course
https://classroom.udacity.com/courses/ud825/
Job Scheduling
in Android
“JobScheduler is
guaranteed to get
your job done”
Job Scheduling
● Running some background tasks outside the scope of an application’s
life-cycle become mainstream
● But they’re expensive
● Scheduling this work intelligently can improve your app’s performance,
along with aspects of system health such as battery life
Job Scheduling
● AlarmManager (Time specific)
● Firebase JobDispatcher (API level >=9 + Google Play Service)
● JobScheduler (API Level >=21)
● 3rd party Evernote Android-Job (API Level >=14)
AlarmManager
● AlarmManager provides access to system-level alarm services
● Registered alarms are retained while the device is asleep but will be cleared if
it is power off and rebooted
● Does not provide more robust execution conditions like device is idle, network
is available or charging detect
AlarmManager Udacity Course
https://classroom.udacity.com/courses/ud853/
Firebase JobDispatcher
● This library will also works when running (using AlarmManager) device do not
have Google play services installed and wants to schedule a job in the
application
● Network State
○ NETWORK_TYPE_NONE
○ NETWORK_TYPE_ANY
○ NETWORK_TYPE_UNMETERED,
○ NETWORK_TYPE_NOT_ROAMING
○ NETWORK_TYPE_METERED
● Charging State
● Idle State
Firebase JobDispatcher Udacity Course
https://classroom.udacity.com/courses/ud851/
JobScheduller
The job implementation consists of the following three steps:
● JobInfo: Sets the conditions under which the job will run
● JobService: implements the necessary action when the job is
executed
● Grants permission of your sub-class of JobService for job execution
android.permission.BIND_JOB_SERVICE
JobScheduller - JobInfo
● Connected network type
● Charging status
● Device idle state
● Updating the content provider
● Clip data
● Execution cycle
● Minimum latency
● Deadline setting
● Retry Policy
● Whether the current condition is maintained when rebooting
JobScheduller - JobInfo
class JobSchedulerSample {
private static final int JOB_ID_UPDATE = 0x1000;
static void setUpdateJob(Context context) {
JobInfo job = new JobInfo.Builder(JOB_ID_UPDATE,
new ComponentName(this, SyncJobService.class)
)
.setRequiresStorageNotLow(true)
.setRequiredNetworksCapabilities(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
JobService mJobService = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
mJobService.scheduleJob(job);
}
}
JobScheduller - JobService
● JobService has an easy structure that can handle the operation start,
finish and notifying the end of the job by calling at any time if
necessary
● onStartJob()
onStartJob()Return true if it need more time to finish your work such
as AsyncTask or Thread thing, and false if the action is finished at this
method
● onStopJob()
Returning true re-schedule the job that are currently running. False to
prevent this job from being scheduled again
JobScheduller - JobService
public class SyncJobService extends JobService {
@Override
public void onCreate() {
. . . . .
}
@Override
public boolean onStartJob(final JobParameters params) {
return mDownloader.hasPendingArtworkDownload();
}
@Override
public boolean onStopJob(JobParameters params) {
return !mDownloader.isFinished();
}
}
JobScheduller - AndroidManifest.xml
<service
android:name=".SyncJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
Job Schedulling
FCM & Places
Have anything to discuss ?
Architecture
Components
A new collection of
libraries that help you
design robust,
testable, and
maintainable apps
Architecture Component
● Persist Data
● Manage Lifecycle
● Makes more modular
● Helps avoid memory leaks
● Less boilerplate code
Room
Robust Persistence data
and SQL mapping library
which work with every
Android versionArchitecture Components
Old days
● Lots boilerplate code
● No direct object mapping
● Difficult to implement database migration
● Difficult to test
● Possible long main thread database operation
Room
Room
Room implementation consists of the following steps:
● Update the gradle dependencies
●  Update model classes to entities
● Create Data Access Objects (DAOs)
● Create the database
Adding Gradle dependencies
dependencies {
...
compile 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
...
}
Create an Entity
@Entity
public class Product {
@PrimaryKey(autoGenerate = true)
private int uid;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "image_url")
private String imageUrl;
// getters and setters
}
public class Warehouse {
String name;
@Embedded
Product product;
}
@Entity
Defines the table name of the database (case-insensitive)
@PrimaryKey
autoGenerate = true / false
@ColumnInfo
Defines the column name of the current table
@Ignore
Ignores the marked element from Room's processing logic
@Embeded
Works like weak entity
@ForeignKey
Relation with another entity
https://developer.android.com/reference/android/arch/persis
tence/room/package-summary.html
Create a Data Access Object
@Dao
public interface CountryDao {
@Query("SELECT * FROM Country")
LiveData<List<Country>> getAll();
@Query("SELECT * FROM Country where name LIKE :name")
Country findByName(String name);
@Query("SELECT COUNT(*) from Country")
int countCountries();
@Insert
void insertAll(Country... countries);
@Delete
void delete(Country country);
}
● Room allows that by providing observable queries
which will notify when the data in the database is
changed/updated.
● The SQL query is checked at the compile time itself
● Support multiple tables
Create a Database
@Database(entities = {Country.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CountryDao countryDao();
public static AppDatabase getAppDatabase(Context
context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "country-database").build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
● The database instance is expensive.
● It is recommended to keep it in a singleton or
dependency injector
● entities: defines the related entities of the current
database. If you have more than one, you can
separate by comma.
● version: defines the database version
Room Codelabs
https://codelabs.developers.google.com/codelabs/android-persistence/#0
ViewModel
Designed to store the UI related
data and this component is lifecycle
aware which allows it to survive the
configuration change automaticallyArchitecture Components
ViewModel
● Manage the data for the UI
● Communication between Activity / Fragment
● Retains the data during the configuration change
● Never ever access your view hierarchy or hold a reference back to the
Activity or the Fragment
ViewModel
ViewModel
ViewModel
Don’t store
Activity/Fragment/View or
Context in a ViewModel
ViewModel
ViewModel !=
onSaveInstanceState()
ViewModel are not persisted if
the application is killed by the
System
Adding Gradle dependencies
dependencies {
...
compile 'android.arch.lifecycle:runtime:1.0.0'
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0'
...
}
Create ViewModel Class
public class CouponViewModel extends ViewModel{
private Coupon coupon;
private CouponRepository couponRepository = new
CouponRepository();
public Coupon getCoupon() {
if(coupon == null){
coupon = couponRepository.getTopCoupon();
}
return coupon;
}
}
This class holds the model object defined in Room / Model
Class and it contains methods to handle UI events which
apply business logic and fetch data and finally set model
Call in Activity
couponViewModel =
ViewModelProviders.of(this).get(CouponViewModel.class);
couponViewModel.getCoupon();
ViewModel Codelabs
https://codelabs.developers.google.com/codelabs/android-lifecycles/
LiveData
Component which holds
the value (data holder) and
allows to observe for
changes in the valueArchitecture Components
LiveData
● Ensures your UI matches your data state & Up to date
● No memory leaks
● No crashes due to stopped activities
● No more manual lifecycle handling
LiveData
ViewModel
● If the Lifecycle is destroyed, the observer is
removed automatically
● If the Lifecycle is not in an active state
(STARTED or RESUMED), the observer isn't
called even if the value changes.
Adding Gradle dependencies
dependencies {
...
compile 'android.arch.lifecycle:runtime:1.0.0'
compile 'android.arch.lifecycle:extensions:1.0.0'
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0'
...
}
Create LiveData Class
public class CouponViewModel extends ViewModel{
private Coupon coupon;
private CouponRepository couponRepository = new
CouponRepository();
public Coupon getCoupon() {
if(coupon == null){
coupon = couponRepository.getTopCoupon();
}
return coupon;
}
}
● Make sure to store LiveData objects that update the
UI in ViewModel objects
Observe LiveData objects
// Get the ViewModel.
mModel =
ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new
Observer<String>() {
@Override
public void onChanged(@Nullable final String
newName) {
// Update the UI, in this case, a TextView.
mNameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity
as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this,
nameObserver);
● LiveData delivers updates only when data changes,
and only to active observers
● Only receives an update if the value has changed
since the last time it became active
Updating LiveData objects
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
mModel.getCurrentName().setValue(anotherName);
}
});
● setValue(T) method to update the LiveData object
from the main thread / UI thread
● postValue(T) method to update the LiveData object in
background thread
LiveData Codelabs
https://codelabs.developers.google.com/codelabs/android-lifecycles/
1 sur 70

Contenu connexe

Tendances

Academy PRO: React JSAcademy PRO: React JS
Academy PRO: React JSBinary Studio
1.1K vues30 diapositives
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJSTu Hoang
314 vues25 diapositives
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJSKnoldus Inc.
2.3K vues14 diapositives
ReactJsReactJs
ReactJsLearningTech
2.6K vues19 diapositives

Tendances(20)

Academy PRO: React JSAcademy PRO: React JS
Academy PRO: React JS
Binary Studio1.1K vues
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
Tu Hoang314 vues
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
Knoldus Inc.2.3K vues
Designing applications with ReduxDesigning applications with Redux
Designing applications with Redux
Fernando Daciuk1.2K vues
Learn react-jsLearn react-js
Learn react-js
C...L, NESPRESSO, WAFAASSURANCE, SOFRECOM ORANGE24.2K vues
ReactJsReactJs
ReactJs
LearningTech2.6K vues
React render propsReact render props
React render props
Saikat Samanta222 vues
Workshop React.jsWorkshop React.js
Workshop React.js
Commit University2.2K vues
Angular 2 Migration - JHipster Meetup 6Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6
William Marques2.6K vues
React - Start learning today React - Start learning today
React - Start learning today
Nitin Tyagi140 vues
Redux jsRedux js
Redux js
Nils Petersohn3.5K vues
React jsReact js
React js
Jai Santhosh26.4K vues
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
洪 鹏发30.1K vues
ReactJS presentationReactJS presentation
ReactJS presentation
Thanh Tuong5.7K vues
Intro to ReactIntro to React
Intro to React
Eric Westfall2.1K vues
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
Harvard Web Working Group3.8K vues

Similaire à Advanced android app development(20)

Microservices and modularity with javaMicroservices and modularity with java
Microservices and modularity with java
DPC Consulting Ltd1.2K vues
Deep dive into Android async operationsDeep dive into Android async operations
Deep dive into Android async operations
Mateusz Grzechociński2.3K vues
Five android architectureFive android architecture
Five android architecture
Tomislav Homan586 vues
Android101Android101
Android101
David Marques1.5K vues
Android best practicesAndroid best practices
Android best practices
Jose Manuel Ortega Candel2.2K vues
Job schedulers androidJob schedulers android
Job schedulers android
Deesha Vora458 vues
Android Pro RecipesAndroid Pro Recipes
Android Pro Recipes
Gabriel Dogaru1.5K vues
Stmik bandungStmik bandung
Stmik bandung
farid savarudin91 vues
What's new in android M(6.0)What's new in android M(6.0)
What's new in android M(6.0)
Yonatan Levin1.6K vues
Droidcon Paris 2015Droidcon Paris 2015
Droidcon Paris 2015
Renaud Boulard191 vues
Clean Architecture @ TaxibeatClean Architecture @ Taxibeat
Clean Architecture @ Taxibeat
Michael Bakogiannis706 vues

Advanced android app development

  • 3. “I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.”
  • 4. Study Group != College Lecture
  • 5. Course and Schedule ● Udacity Advanced Course ○ https://www.udacity.com/courses/ud855 ○ Course Review ○ Project Review ● Additional Course ○ Android Optimization ○ Android Studio Productivity Boost ○ Android Architecture Component
  • 6. Course and Schedule Day 1 ● Fragment ● Libraries Day 2 ● Firebase Cloud Messaging ● Places Day 3 ● Media Playback ● Widget Day 4 ● Espresso ● Publishing Your App
  • 7. Assessment ● 50% Attendance (10%) ● Student progress (15%) ○ 100% View on Udacity Course ○ Understanding, Activeness, Contribution ● Final projects (75%)
  • 8. Example - Screenshot Dashboard MUST BE 100% VIEWED
  • 9. Final Project ● Original work ● Past project is fine ● Sky's the limit ● Containing 2 or more course material ● APK and Documentation / Source code ● Sent to rwpramono@gmail.com ● Due Date is 2 week after last meeting
  • 10. Fragment & Libraries Have anything to discuss ?
  • 11. "A small leak will sink a great ship" Memory Leak
  • 12. Memory Leak ● Every app needs memory as a resource to do its work ● Android runtime triggers Garbage Collection (GC) when memory runs short to reclaim memory by cleaning up objects that are no longer useful ● What if the object is not used anymore in the program but its memory cannot be released by the Garbage Collector ?
  • 13. Memory Leak ● Memory leak causing more frequent GC events ● GC events makes rendering of UI and processing of events will stop ● Potentially more than 16ms drawing window
  • 14. Memory Leak Effects ● No response to an input event (such as key press or screen touch events) within 5 seconds ● A BroadcastReceiver hasn't finished executing within 10 seconds ● The system will eventually refuse to allocate more memory for your app
  • 16. Unregistered listeners public class LeaksActivity extends Activity implements LocationListener { private LocationManager locationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leaks); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, TimeUnit.MINUTES.toMillis(5), 100, this); } // Listener implementation omitted }
  • 17. Unregistered listeners ● Unregister the listener in onDestroy() method @Override protected void onDestroy() { locationManager.removeUpdates(this); super.onDestroy(); }
  • 18. Inner classes public class AsyncActivity extends Activity { . . @Override protected void onCreate(Bundle savedInstanceState) { . . new BackgroundTask().execute(); } private class BackgroundTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { } }
  • 19. Inner classes ● Avoid non-static inner classes private static class BackgroundTask extends AsyncTask<Void, Void, String> { . . } ● Use WeakReference if needed public BackgroundTask(TextView resultTextView) { this.textViewReference = new WeakReference<>(resultTextView); }
  • 20. Anonymous classes private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { . . . . . mLeakyHandler.sendEmptyMessageDelayed(MESSAGE_ID,20000); }
  • 21. Anonymous classes ● Use static Handler class @Override protected void onDestroy() { mLeakyHandler.removeMessages(MESSAGE_ID); super.onDestroy(); }
  • 22. Static Context and View object public class MyActivity extends AppCompatActivity { private static Context sContext; . . . . . }
  • 23. Static Context and View object ● Avoid static to Android components like context, activities, services and views ● Use WeakReference if needed ● Use Application context instead of the Activity context ● Set null in onDestroy() callback
  • 24. Leak Canary ● Created by Pierre-Yves Ricau (Square Inc) ● Very easy to use ● Tracks objects for memory leaks
  • 26. Job Scheduling in Android “JobScheduler is guaranteed to get your job done”
  • 27. Job Scheduling ● Running some background tasks outside the scope of an application’s life-cycle become mainstream ● But they’re expensive ● Scheduling this work intelligently can improve your app’s performance, along with aspects of system health such as battery life
  • 28. Job Scheduling ● AlarmManager (Time specific) ● Firebase JobDispatcher (API level >=9 + Google Play Service) ● JobScheduler (API Level >=21) ● 3rd party Evernote Android-Job (API Level >=14)
  • 29. AlarmManager ● AlarmManager provides access to system-level alarm services ● Registered alarms are retained while the device is asleep but will be cleared if it is power off and rebooted ● Does not provide more robust execution conditions like device is idle, network is available or charging detect
  • 31. Firebase JobDispatcher ● This library will also works when running (using AlarmManager) device do not have Google play services installed and wants to schedule a job in the application ● Network State ○ NETWORK_TYPE_NONE ○ NETWORK_TYPE_ANY ○ NETWORK_TYPE_UNMETERED, ○ NETWORK_TYPE_NOT_ROAMING ○ NETWORK_TYPE_METERED ● Charging State ● Idle State
  • 32. Firebase JobDispatcher Udacity Course https://classroom.udacity.com/courses/ud851/
  • 33. JobScheduller The job implementation consists of the following three steps: ● JobInfo: Sets the conditions under which the job will run ● JobService: implements the necessary action when the job is executed ● Grants permission of your sub-class of JobService for job execution android.permission.BIND_JOB_SERVICE
  • 34. JobScheduller - JobInfo ● Connected network type ● Charging status ● Device idle state ● Updating the content provider ● Clip data ● Execution cycle ● Minimum latency ● Deadline setting ● Retry Policy ● Whether the current condition is maintained when rebooting
  • 35. JobScheduller - JobInfo class JobSchedulerSample { private static final int JOB_ID_UPDATE = 0x1000; static void setUpdateJob(Context context) { JobInfo job = new JobInfo.Builder(JOB_ID_UPDATE, new ComponentName(this, SyncJobService.class) ) .setRequiresStorageNotLow(true) .setRequiredNetworksCapabilities(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build(); JobService mJobService = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); mJobService.scheduleJob(job); } }
  • 36. JobScheduller - JobService ● JobService has an easy structure that can handle the operation start, finish and notifying the end of the job by calling at any time if necessary ● onStartJob() onStartJob()Return true if it need more time to finish your work such as AsyncTask or Thread thing, and false if the action is finished at this method ● onStopJob() Returning true re-schedule the job that are currently running. False to prevent this job from being scheduled again
  • 37. JobScheduller - JobService public class SyncJobService extends JobService { @Override public void onCreate() { . . . . . } @Override public boolean onStartJob(final JobParameters params) { return mDownloader.hasPendingArtworkDownload(); } @Override public boolean onStopJob(JobParameters params) { return !mDownloader.isFinished(); } }
  • 40. FCM & Places Have anything to discuss ?
  • 41. Architecture Components A new collection of libraries that help you design robust, testable, and maintainable apps
  • 42. Architecture Component ● Persist Data ● Manage Lifecycle ● Makes more modular ● Helps avoid memory leaks ● Less boilerplate code
  • 43. Room Robust Persistence data and SQL mapping library which work with every Android versionArchitecture Components
  • 44. Old days ● Lots boilerplate code ● No direct object mapping ● Difficult to implement database migration ● Difficult to test ● Possible long main thread database operation
  • 45. Room
  • 46. Room Room implementation consists of the following steps: ● Update the gradle dependencies ●  Update model classes to entities ● Create Data Access Objects (DAOs) ● Create the database
  • 47. Adding Gradle dependencies dependencies { ... compile 'android.arch.persistence.room:runtime:1.0.0' annotationProcessor 'android.arch.persistence.room:compiler:1.0.0' ... }
  • 48. Create an Entity @Entity public class Product { @PrimaryKey(autoGenerate = true) private int uid; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "image_url") private String imageUrl; // getters and setters } public class Warehouse { String name; @Embedded Product product; } @Entity Defines the table name of the database (case-insensitive) @PrimaryKey autoGenerate = true / false @ColumnInfo Defines the column name of the current table @Ignore Ignores the marked element from Room's processing logic @Embeded Works like weak entity @ForeignKey Relation with another entity https://developer.android.com/reference/android/arch/persis tence/room/package-summary.html
  • 49. Create a Data Access Object @Dao public interface CountryDao { @Query("SELECT * FROM Country") LiveData<List<Country>> getAll(); @Query("SELECT * FROM Country where name LIKE :name") Country findByName(String name); @Query("SELECT COUNT(*) from Country") int countCountries(); @Insert void insertAll(Country... countries); @Delete void delete(Country country); } ● Room allows that by providing observable queries which will notify when the data in the database is changed/updated. ● The SQL query is checked at the compile time itself ● Support multiple tables
  • 50. Create a Database @Database(entities = {Country.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CountryDao countryDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "country-database").build(); } return INSTANCE; } public static void destroyInstance() { INSTANCE = null; } } ● The database instance is expensive. ● It is recommended to keep it in a singleton or dependency injector ● entities: defines the related entities of the current database. If you have more than one, you can separate by comma. ● version: defines the database version
  • 52. ViewModel Designed to store the UI related data and this component is lifecycle aware which allows it to survive the configuration change automaticallyArchitecture Components
  • 53. ViewModel ● Manage the data for the UI ● Communication between Activity / Fragment ● Retains the data during the configuration change ● Never ever access your view hierarchy or hold a reference back to the Activity or the Fragment
  • 57. ViewModel ViewModel != onSaveInstanceState() ViewModel are not persisted if the application is killed by the System
  • 58. Adding Gradle dependencies dependencies { ... compile 'android.arch.lifecycle:runtime:1.0.0' annotationProcessor 'android.arch.lifecycle:compiler:1.0.0' ... }
  • 59. Create ViewModel Class public class CouponViewModel extends ViewModel{ private Coupon coupon; private CouponRepository couponRepository = new CouponRepository(); public Coupon getCoupon() { if(coupon == null){ coupon = couponRepository.getTopCoupon(); } return coupon; } } This class holds the model object defined in Room / Model Class and it contains methods to handle UI events which apply business logic and fetch data and finally set model
  • 60. Call in Activity couponViewModel = ViewModelProviders.of(this).get(CouponViewModel.class); couponViewModel.getCoupon();
  • 62. LiveData Component which holds the value (data holder) and allows to observe for changes in the valueArchitecture Components
  • 63. LiveData ● Ensures your UI matches your data state & Up to date ● No memory leaks ● No crashes due to stopped activities ● No more manual lifecycle handling
  • 65. ViewModel ● If the Lifecycle is destroyed, the observer is removed automatically ● If the Lifecycle is not in an active state (STARTED or RESUMED), the observer isn't called even if the value changes.
  • 66. Adding Gradle dependencies dependencies { ... compile 'android.arch.lifecycle:runtime:1.0.0' compile 'android.arch.lifecycle:extensions:1.0.0' annotationProcessor 'android.arch.lifecycle:compiler:1.0.0' ... }
  • 67. Create LiveData Class public class CouponViewModel extends ViewModel{ private Coupon coupon; private CouponRepository couponRepository = new CouponRepository(); public Coupon getCoupon() { if(coupon == null){ coupon = couponRepository.getTopCoupon(); } return coupon; } } ● Make sure to store LiveData objects that update the UI in ViewModel objects
  • 68. Observe LiveData objects // Get the ViewModel. mModel = ViewModelProviders.of(this).get(NameViewModel.class); // Create the observer which updates the UI. final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { // Update the UI, in this case, a TextView. mNameTextView.setText(newName); } }; // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. mModel.getCurrentName().observe(this, nameObserver); ● LiveData delivers updates only when data changes, and only to active observers ● Only receives an update if the value has changed since the last time it became active
  • 69. Updating LiveData objects mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String anotherName = "John Doe"; mModel.getCurrentName().setValue(anotherName); } }); ● setValue(T) method to update the LiveData object from the main thread / UI thread ● postValue(T) method to update the LiveData object in background thread