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

Introduction to Android Architecture Components

Introduction to Android Architecture Components

Need to understand the basic guidelines for writing Android apps and save yourself from writing a bunch of boring boilerplate code? Join our Google Developer Experts as they take us through the new Android Architecture Components introduced during Google I/O 2017. This month, we will look at introduction to the architecture components, Room, LiveData, ViewModels and Lifecycle.

Rebecca Franks

July 21, 2017
Tweet

More Decks by Rebecca Franks

Other Decks in Programming

Transcript

  1. Intro to Android
    Architecture Components
    #GoogleAfricaDevs

    View Slide

  2. Rebecca Franks
    @riggaroo
    Dario Mungoi
    @DarioMungoi
    Alex Koller
    @AlexKollerDev
    - Intro - Rebecca
    - Room - Dario
    - LiveData - Dario
    - ViewModels - Alex
    - Lifecycle - Rebecca
    - Summary - Dario
    Agenda

    View Slide

  3. What are the new Android Architecture Components?
    - Best Practise Guidelines for writing Android Apps
    - Bunch of different components that can work well separately
    - But - really powerful when used together!
    - Released at Google I/O 2017 - in alpha at the moment

    View Slide

  4. View Slide

  5. Why were they introduced?
    - Never any advice given around how to architect an application
    - Provide some helper classes to handle common scenarios (ie
    Lifecycle changes and screen rotation)
    - Improve app quality overall

    View Slide

  6. Main Components in Architecture Libraries
    4 Different Components:
    - Room - SQLite object mapping library. Similar to ORMlite or greenDAO
    - LiveData - Data holder that keeps a value and allows this to be observed.
    Respects lifecycle.
    - ViewModels - Store and manage UI-related data. Survives configuration
    changes.
    - Lifecycles - Classes that help you manage lifecycle correctly.

    View Slide

  7. http://bit.ly/android-arch
    Sample App

    View Slide

  8. View Slide

  9. Add Architecture Components to your app
    //Add Google Repository to your top
    level build.gradle
    allprojects {
    repositories {
    jcenter()
    google()
    }
    }

    View Slide

  10. Add Architecture Components to your App
    // In your app level build.gradle
    // For Lifecycles, ViewModels, LiveData:
    compile "android.arch.lifecycle:runtime:1.0.0-alpha5"
    compile "android.arch.lifecycle:extensions:1.0.0-alpha5"
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha5"
    // For Room
    compile "android.arch.persistence.room:runtime:1.0.0-alpha5"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha5"

    View Slide

  11. View Slide

  12. Persistence with Room
    By Dario Mungoi

    View Slide

  13. Why should we always persist data?
    Make sure the app is usable even on FLAKY Networks.
    Users don’t like HATE to see LOADING SCREENS.
    Users LOVE you if you cache info and save their DATA and BATTERY.

    View Slide

  14. What is currently available out there?
    Firebase Realm DB Shared Prefs
    SQLite
    Content Providers
    Room
    Our star of the Day

    View Slide

  15. What is Room?
    SQLite object mapping library.
    Similar to ORMlite or greenDAO

    View Slide

  16. Getting started with Room

    View Slide

  17. Create an Entity
    @Entity(tableName = TABLE_NAME)
    public class Event {
    public static final String TABLE_NAME = "events";
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String name;
    private String description;
    // … getters, setters etc
    }

    View Slide

  18. Create a Data Access Object (DAO)
    @Dao
    public interface EventDao {
    @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD +
    " > :minDate")
    List getEvents(LocalDateTime minDate);
    @Insert(onConflict = REPLACE)
    void addEvent(Event event);
    }

    View Slide

  19. Finally create a database and be ready to go!
    @Database(entities = {Event.class}, version = 1)
    public abstract class EventDatabase extends RoomDatabase {
    public abstract EventDao eventDao();
    }
    {
    Room.databaseBuilder(context.getApplicationContext(),
    EventDatabase.class,
    "event_db").build();
    }

    View Slide

  20. Do you have the need of saving custom types
    to the database?

    View Slide

  21. Create a Custom Type Adapter
    public class DateTypeConverter {
    @TypeConverter
    public static LocalDateTime toDate(Long timestamp) {
    //.. Convert when reading the timestamp from the DB
    }
    @TypeConverter
    public static Long toTimestamp(LocalDateTime date) {
    //.. Convert when writing a LocalDateTime object to the DB
    }
    }

    View Slide

  22. Use the Custom Data Type
    @Entity(tableName = TABLE_NAME)
    public class Event {
    public static final String DATE_FIELD = "date";
    //Other entity variables
    @ColumnInfo(name = DATE_FIELD)
    private LocalDateTime date;
    }

    View Slide

  23. Update Database to Support Custom Type Adapter
    @Database(entities = {Event.class}, version = 1)
    @TypeConverters(DateTypeConverter.class)
    public abstract class EventDatabase extends RoomDatabase {
    public abstract EventDao eventDao();
    }

    View Slide

  24. What are other benefits of using Room?
    - SQLite data relationship supported
    - Easily define (multiple) indexes to improve query performance
    - Support for RxJava 2 Flowable, Maybe and Single
    - SQL statement verification at compile time
    - Designed to be testable
    - Easily do database migrations

    View Slide

  25. View Slide

  26. LiveData
    By Dario

    View Slide

  27. What if after running this query...
    @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate")
    List getEvents(LocalDateTime minDate);
    ● The data gets updated in the background?
    ● We want to listen for changes in multiple locations?

    View Slide

  28. LiveData
    “An Observable data holder that is Lifecycle aware and does
    automatic management of Subscriptions”

    View Slide

  29. Return LiveData and Observe for changes
    @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate")
    LiveData> getEvents(LocalDateTime minDate);
    //observe on the UI
    eventDatabase.getEventDao().getEvents().observe(this, new Observer>() {
    @Override
    public void onChanged(@Nullable List performers) {
    //update the recycler view
    }
    });

    View Slide

  30. View Slide

  31. ViewModel
    By Alex

    View Slide

  32. What is a ViewModel?
    - It’s the VM in MVVM architecture (also useful outside of MVVM)
    - A simple class designed to store and manage UI-related data
    - Data survives configuration changes such as screen rotations
    - No leaks (no references to activities, fragments, or views)

    View Slide

  33. How do ViewModels fit into the big picture?
    - Sits between UI and
    data/business logic
    - Simpler, slimmer Activities
    - Repository pattern

    View Slide

  34. Surviving rotations
    - VM is scoped to a Lifecycle
    - VM reattached to
    Activity/Fragment when recreated
    after config change
    - VM cleans up after itself
    - it just works!

    View Slide

  35. ViewModel vs SavedInstanceState
    - VMs can be shared between UI components
    - VMs are not persisted if the application is killed by the OS
    - SIS kept in system process memory - use sparingly!
    - Typical usage:
    - Store event ID in SavedInstanceState
    - Lookup Event object from ID and store in ViewModel

    View Slide

  36. Creating your ViewModel
    public class EventListViewModel extends ViewModel {
    private List events;
    public EventListViewModel() {
    // Load data once in constructor
    // Don’t do work on the main thread, see next example
    events = EventRepository.getInstance().loadAll();
    }
    public List getEvents() { return events; }
    }

    View Slide

  37. Getting and using your ViewModel
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get our VM (tied to the scope of this Activity)
    viewModel = ViewModelProviders.of(this)
    .get(EventListViewModel.class);
    // ...
    events = viewModel.getEvents();
    }

    View Slide

  38. Useful on its own, powerful with its friends
    - VMs can be used without any other architecture components
    - Separate your code, decouple UI from business logic/data loading
    - More testable
    - More useful when used with LiveData - observe changes to data

    View Slide

  39. Extending your ViewModel with LiveData
    public class EventListViewModel extends ViewModel {
    private LiveData> events;
    public EventListViewModel() {
    // Load data once in constructor
    // OK on main thread - it returns observable LiveData
    events = EventRepository.getInstance().loadAll();
    }
    public LiveData> getEvents() { return events;
    }
    }

    View Slide

  40. Getting and observing your ViewModel
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get our VM (tied to the scope of this Activity)
    viewModel = ViewModelProviders.of(this)
    .get(EventListViewModel.class);
    // Observer event list data
    viewModel.getEvents().observe(this, events -> {
    this.events = events;
    });
    }

    View Slide

  41. ViewModel tips & tricks
    - Extend AndroidViewModel if you need access to a Context
    - Share data between Fragments by using their Activity’s scope

    View Slide

  42. View Slide

  43. Lifecycle + Lifecycle Aware
    Components
    By Rebecca

    View Slide

  44. Handling Lifecycles
    - Interfaces that let you build lifecycle aware components
    - Automatically adjust behaviour according to the current
    lifecycle
    - Helps avoid memory leaks and complex activity/fragment code

    View Slide

  45. Lifecycle - State & Event Enums

    View Slide

  46. Handling Lifecycles - Old Way
    public class VideoActivity extends Activity {
    public void onStart(){
    videoPlayer.start();
    analytics.start();
    //..
    }
    public void onStop(){
    videoPlayer.stop();
    analytics.stop();
    //..
    }
    }

    View Slide

  47. Making a Lifecycle Aware Component
    public class VideoPlayerComponent implements LifecycleObserver {
    }
    bit.ly/arch-lifecycle-video
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart() {
    // do something
    }
    public void enable() {
    if (lifecycle.getState().isAtLeast(STARTED)) {
    // do something
    }
    }

    View Slide

  48. LiveData is a Lifecycle Aware Component

    View Slide

  49. LifecycleOwner
    - LifecycleOwner is a single method interface that indicates that
    the class has a Lifecycle
    - getLifecycle() must be implemented by the class
    - LifecycleActivity & LifecycleFragment implement LifecycleOwner
    (these classes will be deprecated once components are live)

    View Slide

  50. LifecycleOwner
    public class VideoActivity extends LifecycleActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    }
    }
    getLifecycle().addObserver(new VideoPlayerComponent());

    View Slide

  51. View Slide

  52. Summary

    View Slide

  53. Summary
    - Architecture Components are a welcome addition to Android
    - Helps solve complex problems like screen rotation and lifecycles
    management
    - Helps mitigate memory leaks and exceptions due to being in the
    incorrect state
    - Simplifies code, makes your code cleaner and easier to test

    View Slide

  54. Thank you!
    developer.android.com/arch
    bit.ly/arch-guide
    Rebecca Franks
    @riggaroo
    Dario Mungoi
    @DarioMungoi
    Alex Koller
    @AlexKollerDev
    #GoogleAfricaDevs

    View Slide

  55. Q&A
    Rebecca Franks
    @riggaroo
    Dario Mungoi
    @DarioMungoi
    Alex Koller
    @AlexKollerDev
    #GoogleAfricaDevs

    View Slide