Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Devfest '17] Architecture Components

[Devfest '17] Architecture Components

Get to know the new Architecture Components released by Google in I/O'17

Gave this talk for GDG Cloud Vancouver Devfest'17
Animated GIF version: https://goo.gl/dVj63L

Nishant Srivastava

October 14, 2017
Tweet

More Decks by Nishant Srivastava

Other Decks in Technology

Transcript

  1. View Slide

  2. View Slide

  3. @nisrulz
    #devfest17

    View Slide

  4. @nisrulz
    #devfest17

    View Slide

  5. @nisrulz
    #devfest17

    View Slide

  6. @nisrulz
    #devfest17

    View Slide

  7. @nisrulz
    #devfest17

    View Slide

  8. @nisrulz
    #devfest17

    View Slide

  9. @nisrulz
    #devfest17

    View Slide

  10. @nisrulz
    #devfest17

    View Slide

  11. @nisrulz
    #devfest17

    View Slide

  12. @nisrulz
    #devfest17

    View Slide

  13. @nisrulz
    #devfest17

    View Slide

  14. @nisrulz
    #devfest17

    View Slide

  15. @nisrulz
    #devfest17

    View Slide

  16. @nisrulz
    #devfest17

    View Slide

  17. @nisrulz
    #devfest17

    View Slide

  18. @nisrulz
    #devfest17

    View Slide

  19. @nisrulz
    #devfest17

    View Slide

  20. @nisrulz
    #devfest17

    View Slide

  21. @nisrulz
    #devfest17

    View Slide

  22. @nisrulz
    #devfest17


    View Slide

  23. @nisrulz
    #devfest17



    View Slide

  24. @nisrulz
    #devfest17




    View Slide

  25. @nisrulz
    #devfest17





    View Slide

  26. // Project’s root build.gradle
    allprojects {
    repositories {
    jcenter()
    maven { url 'https://maven.google.com' } // or use google()
    }
    }
    @nisrulz
    #devfest17

    View Slide

  27. // Project’s root build.gradle
    allprojects {
    repositories {
    jcenter()
    maven { url 'https://maven.google.com' } // or use google()
    }
    }
    @nisrulz
    #devfest17

    View Slide

  28. // app’s build.gradle
    // For Lifecycles, LiveData, and ViewModel, add:
    implementation "android.arch.lifecycle:runtime:1.0.0"
    implementation "android.arch.lifecycle:extensions:1.0.0-beta2"
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0-beta2"
    @nisrulz
    #devfest17

    View Slide

  29. @nisrulz
    #devfest17

    View Slide

  30. class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
    // ...
    }
    void start() {
    // connect to system location service
    }
    void stop() {
    // disconnect from system location service
    }
    }
    @nisrulz
    #devfest17

    View Slide

  31. class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
    // ...
    }
    void start() {
    // connect to system location service
    }
    void stop() {
    // disconnect from system location service
    }
    }
    @nisrulz
    #devfest17

    View Slide

  32. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate(...) {
    myLocationListener = new MyLocationListener(this, (location) -> {
    // update UI
    });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  33. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate(...) {
    myLocationListener = new MyLocationListener(this, (location) -> {
    // update UI
    });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  34. class MyActivity extends AppCompatActivity {
    // ..
    public void onStart() {
    super.onStart();
    myLocationListener.start();
    }
    public void onStop() {
    super.onStop();
    myLocationListener.stop();
    }
    }
    @nisrulz
    #devfest17

    View Slide

  35. class MyActivity extends AppCompatActivity {
    // ..
    public void onStart() {
    super.onStart();
    myLocationListener.start();
    }
    public void onStop() {
    super.onStop();
    myLocationListener.stop();
    }
    }
    @nisrulz
    #devfest17

    View Slide

  36. class MyActivity extends AppCompatActivity {
    //...
    public void onStart() {
    super.onStart();
    Util.checkUserStatus(result -> {
    // what if this callback is invoked AFTER activity is stopped?
    if (result) {
    myLocationListener.start();
    }
    });
    }
    // onStop()
    }
    @nisrulz
    #devfest17

    View Slide

  37. class MyActivity extends AppCompatActivity {
    //...
    public void onStart() {
    super.onStart();
    Util.checkUserStatus(result -> {
    // what if this callback is invoked AFTER activity is stopped?
    if (result) {
    myLocationListener.start();
    }
    });
    }
    // onStop()
    }
    @nisrulz
    #devfest17

    View Slide

  38. @nisrulz
    #devfest17

    View Slide

  39. Lifecycle Owner
    Class with lifecycle i.e Activity & Fragments
    @nisrulz
    #devfest17

    View Slide

  40. Lifecycle Owner
    Class with lifecycle i.e Activity & Fragments
    Lifecycle Observer
    Class that observe lifecycle
    @nisrulz
    #devfest17

    View Slide

  41. @nisrulz
    #devfest17

    View Slide

  42. public class MyLocationListener implements LifecycleObserver {
    public MyLocationListener(Context context,
    Lifecycle lifecycle,
    Callback callback) {
    // ...
    lifecycle.addObserver(this);
    }
    }
    @nisrulz
    #devfest17

    View Slide

  43. public class MyLocationListener implements LifecycleObserver {
    public MyLocationListener(Context context,
    Lifecycle lifecycle,
    Callback callback) {
    // ...
    lifecycle.addObserver(this);
    }
    }
    @nisrulz
    #devfest17

    View Slide

  44. public class MyLocationListener implements LifecycleObserver {
    // ...
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void start() {
    // connect to system location service
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void stop() {
    // disconnect from system location service
    }
    }
    @nisrulz
    #devfest17

    View Slide

  45. public class MyLocationListener implements LifecycleObserver {
    // ...
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void start() {
    // connect to system location service
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void stop() {
    // disconnect from system location service
    }
    }
    @nisrulz
    #devfest17

    View Slide

  46. public class MyLocationListener implements LifecycleObserver {
    // ...
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void cleanup() {
    lifecycle.removeObserver(this);
    }
    }
    @nisrulz
    #devfest17

    View Slide

  47. public class MyLocationListener implements LifecycleObserver {
    // ...
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void cleanup() {
    lifecycle.removeObserver(this);
    }
    }
    @nisrulz
    #devfest17

    View Slide

  48. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate() {
    myLocationListener =
    new MyLocationListener(this,
    getLifecycle(),
    location -> { //update UI });
    Util.checkUserStatus(result -> { //... });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  49. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate() {
    myLocationListener =
    new MyLocationListener(this,
    getLifecycle(),
    location -> { //update UI });
    Util.checkUserStatus(result -> { //... });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  50. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate() {
    myLocationListener =
    new MyLocationListener(this,
    getLifecycle(),
    location -> { //update UI });
    Util.checkUserStatus(result -> { //... });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  51. class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;
    public void onCreate() {
    myLocationListener =
    new MyLocationListener(this,
    getLifecycle(),
    location -> { //update UI });
    Util.checkUserStatus(result -> { //... });
    }
    }
    @nisrulz
    #devfest17

    View Slide

  52. As of release of Support Library v26.1.0
    @nisrulz
    #devfest17

    View Slide

  53. As of release of Support Library v26.1.0
    “Fragment and FragmentActivity (the base class for
    AppCompatActivity) now implement the LifecycleOwner
    interface from Architecture Components”
    @nisrulz
    #devfest17

    View Slide

  54. @nisrulz
    #devfest17

    View Slide

  55. @nisrulz
    #devfest17

    View Slide

  56. @nisrulz
    #devfest17

    View Slide

  57. @nisrulz
    #devfest17

    View Slide

  58. @nisrulz
    #devfest17

    View Slide

  59. @nisrulz
    #devfest17

    View Slide

  60. @nisrulz
    #devfest17

    View Slide

  61. @nisrulz
    #devfest17

    View Slide

  62. @nisrulz
    #devfest17

    View Slide

  63. class LocationManager extends LiveData{
    // ...
    }
    @nisrulz
    #devfest17

    View Slide

  64. class LocationManager extends LiveData{
    @override
    protected void onActive(){
    super.onActive();
    // connect to location
    }
    @override
    protected void onInactive(){
    super.onInactive();
    // disconnect from location
    }
    }
    @nisrulz
    #devfest17

    View Slide

  65. class LocationManager extends LiveData{
    @override
    protected void onActive(){
    super.onActive();
    // connect to location
    }
    @override
    protected void onInactive(){
    super.onInactive();
    // disconnect from location
    }
    }
    @nisrulz
    #devfest17

    View Slide

  66. class MyActivity extends AppCompatActivity {
    public void onCreate(...) {
    LocationManager.getInstance().observe(this,
    location -> {
    //Location Changed
    })
    }
    }
    @nisrulz
    #devfest17

    View Slide

  67. class MyActivity extends AppCompatActivity {
    public void onCreate(...) {
    LocationManager.getInstance().observe(this,
    location -> {
    //Location Changed
    })
    }
    }
    @nisrulz
    #devfest17

    View Slide

  68. @nisrulz
    #devfest17

    View Slide

  69. @nisrulz
    #devfest17

    View Slide

  70. @nisrulz
    #devfest17
    It is the VM in MVVM architecture

    View Slide

  71. @nisrulz
    #devfest17
    It is the VM in MVVM architecture
    A simple class to store and manage ui-related data

    View Slide

  72. @nisrulz
    #devfest17
    It is the VM in MVVM architecture
    A simple class to store and manage ui-related data
    Data survives configuration changes such as screen rotation

    View Slide

  73. @nisrulz
    #devfest17
    It is the VM in MVVM architecture
    A simple class to store and manage ui-related data
    Data survives configuration changes such as screen rotation
    No memory leaks (no references to activity or fragment or views)

    View Slide

  74. @nisrulz
    #devfest17

    View Slide

  75. @nisrulz
    #devfest17
    public class MyViewModel extends ViewModel {
    private MutableLiveData> users;
    public LiveData> getUsers() {
    if (users == null) {
    users = new MutableLiveData>();
    loadUsers();
    }
    return users;
    }
    private void loadUsers() {
    // do async operation to fetch users
    }
    }

    View Slide

  76. @nisrulz
    #devfest17
    public class MyViewModel extends ViewModel {
    private MutableLiveData> users;
    public LiveData> getUsers() {
    if (users == null) {
    users = new MutableLiveData>();
    loadUsers();
    }
    return users;
    }
    private void loadUsers() {
    // do async operation to fetch users
    }
    }

    View Slide

  77. @nisrulz
    #devfest17
    public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
    MyViewModel model = ViewModelProviders
    .of(this)
    .get(MyViewModel.class);
    model.getUsers().observe(this, users -> {
    // update UI
    });
    }
    }

    View Slide

  78. @nisrulz
    #devfest17
    public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
    MyViewModel model = ViewModelProviders
    .of(this)
    .get(MyViewModel.class);
    model.getUsers().observe(this, users -> {
    // update UI
    });
    }
    }

    View Slide

  79. @nisrulz
    #devfest17

    View Slide

  80. @nisrulz
    #devfest17
    ViewModels
    - provide a convenient way to retain data across configuration
    changes
    - they are not persisted if the application is killed by the operating
    system.

    View Slide

  81. @nisrulz
    #devfest17
    ViewModels
    - provide a convenient way to retain data across configuration
    changes
    - they are not persisted if the application is killed by the operating
    system.
    SavedInstanceState
    - stores data, usually ID
    - they are saved in system process memory, OS limits the amount

    View Slide

  82. @nisrulz
    #devfest17

    View Slide

  83. @nisrulz
    #devfest17

    View Slide

  84. @nisrulz
    #devfest17

    View Slide

  85. @nisrulz
    #devfest17

    View Slide

  86. @nisrulz
    #devfest17

    View Slide

  87. @nisrulz
    #devfest17

    View Slide

  88. @nisrulz
    #devfest17

    View Slide

  89. @nisrulz
    #devfest17

    View Slide

  90. @nisrulz
    #devfest17

    View Slide

  91. @nisrulz
    #devfest17

    View Slide

  92. @nisrulz
    #devfest17

    View Slide

  93. @nisrulz
    #devfest17

    View Slide

  94. @nisrulz
    #devfest17

    View Slide

  95. // app’s build.gradle
    // For Room, add:
    implementation "android.arch.persistence.room:runtime:1.0.0-beta2"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0-beta2"
    @nisrulz
    #devfest17

    View Slide

  96. @nisrulz
    #devfest17

    View Slide

  97. @nisrulz
    #devfest17
    @Entity
    public class User {
    @PrimaryKey
    private int uid;
    @ColumnInfo(name = "first_name")
    private String firstName;
    @ColumnInfo(name = "last_name")
    private String lastName;
    // Getters and setters are ignored for brevity,
    // but they're required for Room to work.
    }

    View Slide

  98. @nisrulz
    #devfest17
    @Entity
    public class User {
    @PrimaryKey
    private int uid;
    @ColumnInfo(name = "first_name")
    private String firstName;
    @ColumnInfo(name = "last_name")
    private String lastName;
    // Getters and setters are ignored for brevity,
    // but they're required for Room to work.
    }

    View Slide

  99. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  100. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  101. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  102. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  103. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    }

    View Slide

  104. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    }

    View Slide

  105. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    }

    View Slide

  106. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    }

    View Slide

  107. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    // ..
    private static AppDatabase INSTANCE;
    public static AppDatabase getDatabase(Context context) {
    if (INSTANCE == null) {
    INSTANCE= Room
    .databaseBuilder(getApplicationContext(),
    AppDatabase.class,
    "db_name")
    .build();
    }
    return INSTANCE;
    }
    }

    View Slide

  108. @nisrulz
    #devfest17
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
    // ..
    private static AppDatabase INSTANCE;
    public static AppDatabase getDatabase(Context context) {
    if (INSTANCE == null) {
    INSTANCE= Room
    .databaseBuilder(getApplicationContext(),
    AppDatabase.class,
    "db_name")
    .build();
    }
    return INSTANCE;
    }
    }

    View Slide

  109. @nisrulz
    #devfest17
    // ..
    INSTANCE= Room
    .databaseBuilder(getApplicationContext(),
    AppDatabase.class,
    "db_name")
    .build();

    View Slide

  110. @nisrulz
    #devfest17
    // Get db
    AppDatabase appDatabase = AppDatabase
    .getDatabase(application);
    // Get data from db using the DAO
    List userList = appDatabase
    .userDao()
    .getAll();

    View Slide

  111. @nisrulz
    #devfest17

    View Slide

  112. @nisrulz
    #devfest17
    Compile time SQL statement verification

    View Slide

  113. @nisrulz
    #devfest17
    Compile time SQL statement verification
    Testable

    View Slide

  114. @nisrulz
    #devfest17
    Compile time SQL statement verification
    Testable
    Support for RxJava 2

    View Slide

  115. @nisrulz
    #devfest17
    Compile time SQL statement verification
    Testable
    Support for RxJava 2
    SQLite data relationship supported

    View Slide

  116. @nisrulz
    #devfest17
    Compile time SQL statement verification
    Testable
    Support for RxJava 2
    SQLite data relationship supported
    Easily define multiple indexes to improve query performance

    View Slide

  117. @nisrulz
    #devfest17

    View Slide

  118. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  119. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    LiveData> getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  120. @nisrulz
    #devfest17
    @Dao
    public interface UserDao {
    @Query("SELECT * FROM user")
    LiveData> getAll();
    @Insert
    void insertAll(User... users);
    @Delete
    void delete(User user);
    }

    View Slide

  121. @nisrulz
    #devfest17

    View Slide

  122. @nisrulz
    #devfest17

    View Slide

  123. @nisrulz
    #devfest17
    Data takes time to load

    View Slide

  124. @nisrulz
    #devfest17
    Data takes time to load
    Performance lag

    View Slide

  125. @nisrulz
    #devfest17
    Data takes time to load
    Performance lag
    Too much memory wasted

    View Slide

  126. @nisrulz
    #devfest17
    Gradually load information as needed
    from a data source, without overloading
    the device or waiting too long for a big
    database query.

    View Slide

  127. @nisrulz
    #devfest17

    View Slide

  128. @nisrulz
    #devfest17

    View Slide

  129. // app’s build.gradle
    // For Paging, add:
    implementation "android.arch.paging:runtime:1.0.0-alpha3"
    @nisrulz
    #devfest17

    View Slide

  130. @nisrulz
    #devfest17
    // If you use Room lib to manage your data
    @Query("select * from users WHERE age > :age order by name DESC, id ASC")
    TiledDataSource usersOlderThan(int age);

    View Slide

  131. @nisrulz
    #devfest17
    Loads data from a DataSource.
    You can configure how much data
    - is loaded at a time
    - should be prefetched
    (minimizing the amount of time your users have to wait for data to be loaded)

    View Slide

  132. @nisrulz
    #devfest17
    Implementation of RecyclerView.Adapter that presents data from a
    PagedLi

    View Slide

  133. @nisrulz
    #devfest17

    View Slide

  134. @nisrulz
    #devfest17

    View Slide

  135. @nisrulz
    #devfest17

    View Slide

  136. @nisrulz
    #devfest17

    View Slide

  137. View Slide

  138. View Slide