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. Rebecca Franks @riggaroo Dario Mungoi @DarioMungoi Alex Koller @AlexKollerDev -

    Intro - Rebecca - Room - Dario - LiveData - Dario - ViewModels - Alex - Lifecycle - Rebecca - Summary - Dario Agenda
  2. 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
  3. 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
  4. 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.
  5. Add Architecture Components to your app //Add Google Repository to

    your top level build.gradle allprojects { repositories { jcenter() google() } }
  6. 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"
  7. 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.
  8. What is currently available out there? Firebase Realm DB Shared

    Prefs SQLite Content Providers Room Our star of the Day
  9. 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 }
  10. Create a Data Access Object (DAO) @Dao public interface EventDao

    { @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate") List<Event> getEvents(LocalDateTime minDate); @Insert(onConflict = REPLACE) void addEvent(Event event); }
  11. 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(); }
  12. 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 } }
  13. 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; }
  14. 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(); }
  15. 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
  16. What if after running this query... @Query("SELECT * FROM "

    + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate") List<Event> getEvents(LocalDateTime minDate); • The data gets updated in the background? • We want to listen for changes in multiple locations?
  17. LiveData<T> “An Observable data holder that is Lifecycle aware and

    does automatic management of Subscriptions”
  18. Return LiveData and Observe for changes @Query("SELECT * FROM "

    + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate") LiveData<List<Event>> getEvents(LocalDateTime minDate); //observe on the UI eventDatabase.getEventDao().getEvents().observe(this, new Observer<List<Performer>>() { @Override public void onChanged(@Nullable List<Performer> performers) { //update the recycler view } });
  19. 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)
  20. How do ViewModels fit into the big picture? - Sits

    between UI and data/business logic - Simpler, slimmer Activities - Repository pattern
  21. 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!
  22. 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
  23. Creating your ViewModel public class EventListViewModel extends ViewModel { private

    List<Event> 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<Event> getEvents() { return events; } }
  24. 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(); }
  25. 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
  26. Extending your ViewModel with LiveData public class EventListViewModel extends ViewModel

    { private LiveData<List<Event>> events; public EventListViewModel() { // Load data once in constructor // OK on main thread - it returns observable LiveData events = EventRepository.getInstance().loadAll(); } public LiveData<List<Event>> getEvents() { return events; } }
  27. 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; }); }
  28. ViewModel tips & tricks - Extend AndroidViewModel if you need

    access to a Context - Share data between Fragments by using their Activity’s scope
  29. 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
  30. Handling Lifecycles - Old Way public class VideoActivity extends Activity

    { public void onStart(){ videoPlayer.start(); analytics.start(); //.. } public void onStop(){ videoPlayer.stop(); analytics.stop(); //.. } }
  31. 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 } }
  32. 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)
  33. LifecycleOwner public class VideoActivity extends LifecycleActivity { @Override protected void

    onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } } getLifecycle().addObserver(new VideoPlayerComponent());
  34. 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