Slide 1

Slide 1 text

Lifecycle, LiveData, ViewModel Architecture Components Hugo Visser @botteaap [email protected]

Slide 2

Slide 2 text

Architecture Components ● Guide ○ Reference architecture ○ Sample app ● Components ○ Lifecycle ○ LiveData ○ ViewModel ○ Room → http://littlerobots.nl/blog/cupboard-room/ https://developer.android.com/arch

Slide 3

Slide 3 text

Components ● Best architecture is the one that works for you ○ Separation of concerns ○ Testable ○ Consistent ○ ● Implement it using Architecture Components ○ Solve common Android problems ○ Pick and choose the ones you need

Slide 4

Slide 4 text

Lifecycle

Slide 5

Slide 5 text

Why? ● Components need to respect the Activity / Fragment lifecycle ● Components need to know about the lifecycle state

Slide 6

Slide 6 text

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); myLocationListener = new MyLocationListener(this::handleLocation); } @Override protected void onStart() { super.onStart(); myLocationListener.onStart(); // start other things } @Override protected void onStop() { myLocationListener.onStop(); // stop other things super.onStop(); }

Slide 7

Slide 7 text

public class ArchActivity extends LifecycleActivity { private MyLocationListener myLocationListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); myLocationListener = new MyLocationListener(getLifecycle(), this::handleLocation); } }

Slide 8

Slide 8 text

public class MyLocationListener implements LifecycleObserver { public MyLocationListener(Lifecycle lifecycle, Callback callback) { lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { } }

Slide 9

Slide 9 text

public class MyLocationListener implements LifecycleObserver { public MyLocationListener(Lifecycle lifecycle, Callback callback) { lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { } }

Slide 10

Slide 10 text

public class MyLocationListener implements LifecycleObserver { public MyLocationListener(Lifecycle lifecycle, Callback callback) { lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { } }

Slide 11

Slide 11 text

public class MyLocationListener implements LifecycleObserver { public MyLocationListener(Lifecycle lifecycle, Callback callback) { lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) void onStart() { } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void onStop() { } }

Slide 12

Slide 12 text

public class ArchActivity extends LifecycleActivity { private MyLocationListener myLocationListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); myLocationListener = new MyLocationListener(getLifecycle(), this::handleLocation); } }

Slide 13

Slide 13 text

public class ArchActivity extends LifecycleActivity { private MyLocationListener myLocationListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); myLocationListener = new MyLocationListener(getLifecycle(), this::handleLocation); } }

Slide 14

Slide 14 text

public class MyLocationListener implements LifecycleObserver { private final Lifecycle mLifecycle; public MyLocationListener(Lifecycle lifecycle, Callback callback) { mLifecycle = lifecycle; lifecycle.addObserver(this); } public void enable() { if (mLifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { // do things } else { // defer things } } }

Slide 15

Slide 15 text

Lifecycle ● Get the Lifecycle class from the LivecyleOwner and observe it ● Annotate methods with @OnLifecycleEvent ● Easy to check current state and compare it ● Components are self-contained, Activity boilerplate reduced!

Slide 16

Slide 16 text

LiveData

Slide 17

Slide 17 text

Reactive data holder ● Respond to data change, don’t poll → reactive ● Lifecycle aware component → it relies on Lifecycle

Slide 18

Slide 18 text

LiveData

Slide 19

Slide 19 text

Observable

Slide 20

Slide 20 text

Observable io.reactivex.

Slide 21

Slide 21 text

Observable java.util.

Slide 22

Slide 22 text

Observable android.database.

Slide 23

Slide 23 text

Observable android.databinding.

Slide 24

Slide 24 text

¯\_(ツ)_/¯

Slide 25

Slide 25 text

LiveData

Slide 26

Slide 26 text

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // LiveData LocationLiveData locationLiveData = new LocationLiveData(); // Automatically unregistered when the activity is destroyed // If this has an initial value, it won't be delivered yet! locationLiveData.observe(this, this::handleLocation); } private void handleLocation(Location location) { // won't receive any callbacks until the activity is started or resumed }

Slide 27

Slide 27 text

public class LocationLiveData extends LiveData implements LocationListener { @Override protected void onActive() { startListeningForLocation(); } @Override protected void onInactive() { stopListeningForLocation(); } @Override public void onLocationChanged(Location location) { // this value will be cached and delivered to all observers setValue(location); } }

Slide 28

Slide 28 text

LiveData ● Pass it to functions, model ● Can defer work until there are observers ● MutableLiveData for simple cases (but expose as LiveData)

Slide 29

Slide 29 text

ViewModel

Slide 30

Slide 30 text

Why? ● Scope view model to Activity or Fragment → single instance ● Retain model across life cycle changes (rotation) ● Share model across fragments (using the activity context)

Slide 31

Slide 31 text

public class MyViewModel extends ViewModel { private MutableLiveData> mUsers; public LiveData> getUsers() { if (mUsers == null) { mUsers = new MutableLiveData<>(); loadUsers(); } return mUsers; } private void loadUsers() { // do async operation to fetch users and later use // mUsers.postValue(users) } @Override protected void onCleared() { // Cancel pending operations } }

Slide 32

Slide 32 text

public class MyActivity extends FragmentActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // The Activity acts as the scope. // If the model does not exist in this scope, it’s created. // Otherwise the existing model is returned MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); } }

Slide 33

Slide 33 text

ViewModel ● Easy way to retain data or objects scoped to Activity or Fragment ● Should not contain references to Views ● Combination w/ LiveData

Slide 34

Slide 34 text

Architecture components ● Allow you to tackle common architectural problems specific to Android ● Mix and match ● More to come!

Slide 35

Slide 35 text

Thanks! @botteaap hugo@littlerobots https://www.youtube.com/watch?v=vOJCrbr144o https://d.android.com/arch