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. @nisrulz
    #devfest17

    View full-size slide

  2. @nisrulz
    #devfest17

    View full-size slide

  3. @nisrulz
    #devfest17

    View full-size slide

  4. @nisrulz
    #devfest17

    View full-size slide

  5. @nisrulz
    #devfest17

    View full-size slide

  6. @nisrulz
    #devfest17

    View full-size slide

  7. @nisrulz
    #devfest17

    View full-size slide

  8. @nisrulz
    #devfest17

    View full-size slide

  9. @nisrulz
    #devfest17

    View full-size slide

  10. @nisrulz
    #devfest17

    View full-size slide

  11. @nisrulz
    #devfest17

    View full-size slide

  12. @nisrulz
    #devfest17

    View full-size slide

  13. @nisrulz
    #devfest17

    View full-size slide

  14. @nisrulz
    #devfest17

    View full-size slide

  15. @nisrulz
    #devfest17

    View full-size slide

  16. @nisrulz
    #devfest17

    View full-size slide

  17. @nisrulz
    #devfest17

    View full-size slide

  18. @nisrulz
    #devfest17

    View full-size slide

  19. @nisrulz
    #devfest17

    View full-size slide

  20. @nisrulz
    #devfest17


    View full-size slide

  21. @nisrulz
    #devfest17



    View full-size slide

  22. @nisrulz
    #devfest17




    View full-size slide

  23. @nisrulz
    #devfest17





    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. // 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 full-size slide

  27. @nisrulz
    #devfest17

    View full-size slide

  28. 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 full-size slide

  29. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  34. 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 full-size slide

  35. 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 full-size slide

  36. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  39. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  42. 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 full-size slide

  43. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

  51. 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 full-size slide

  52. @nisrulz
    #devfest17

    View full-size slide

  53. @nisrulz
    #devfest17

    View full-size slide

  54. @nisrulz
    #devfest17

    View full-size slide

  55. @nisrulz
    #devfest17

    View full-size slide

  56. @nisrulz
    #devfest17

    View full-size slide

  57. @nisrulz
    #devfest17

    View full-size slide

  58. @nisrulz
    #devfest17

    View full-size slide

  59. @nisrulz
    #devfest17

    View full-size slide

  60. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

  62. 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 full-size slide

  63. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  66. @nisrulz
    #devfest17

    View full-size slide

  67. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  70. @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 full-size slide

  71. @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 full-size slide

  72. @nisrulz
    #devfest17

    View full-size slide

  73. @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 full-size slide

  74. @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 full-size slide

  75. @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 full-size slide

  76. @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 full-size slide

  77. @nisrulz
    #devfest17

    View full-size slide

  78. @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 full-size slide

  79. @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 full-size slide

  80. @nisrulz
    #devfest17

    View full-size slide

  81. @nisrulz
    #devfest17

    View full-size slide

  82. @nisrulz
    #devfest17

    View full-size slide

  83. @nisrulz
    #devfest17

    View full-size slide

  84. @nisrulz
    #devfest17

    View full-size slide

  85. @nisrulz
    #devfest17

    View full-size slide

  86. @nisrulz
    #devfest17

    View full-size slide

  87. @nisrulz
    #devfest17

    View full-size slide

  88. @nisrulz
    #devfest17

    View full-size slide

  89. @nisrulz
    #devfest17

    View full-size slide

  90. @nisrulz
    #devfest17

    View full-size slide

  91. @nisrulz
    #devfest17

    View full-size slide

  92. @nisrulz
    #devfest17

    View full-size slide

  93. // 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 full-size slide

  94. @nisrulz
    #devfest17

    View full-size slide

  95. @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 full-size slide

  96. @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 full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  105. @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 full-size slide

  106. @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 full-size slide

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

    View full-size slide

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

    View full-size slide

  109. @nisrulz
    #devfest17

    View full-size slide

  110. @nisrulz
    #devfest17
    Compile time SQL statement verification

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  114. @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 full-size slide

  115. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  119. @nisrulz
    #devfest17

    View full-size slide

  120. @nisrulz
    #devfest17

    View full-size slide

  121. @nisrulz
    #devfest17
    Data takes time to load

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  124. @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 full-size slide

  125. @nisrulz
    #devfest17

    View full-size slide

  126. @nisrulz
    #devfest17

    View full-size slide

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

    View full-size slide

  128. @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 full-size slide

  129. @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 full-size slide

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

    View full-size slide

  131. @nisrulz
    #devfest17

    View full-size slide

  132. @nisrulz
    #devfest17

    View full-size slide

  133. @nisrulz
    #devfest17

    View full-size slide

  134. @nisrulz
    #devfest17

    View full-size slide