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

Android Architecture Components

Android Architecture Components

Ihor Dzikovskyy

December 02, 2017
Tweet

More Decks by Ihor Dzikovskyy

Other Decks in Programming

Transcript

  1. Android Architecture Components A collection of libraries that help you

    design robust, testable, and maintainable apps. • Lifecycle-Aware Components • LiveData • ViewModel
  2. Lifecycle is an object that defines an Android Lifecycle LifecycleOwner

    is an interface for objects with a Lifecycle LifecycleObserver is as interface for observing a LifecycleOwner Lifecycle-Aware Components Fragments and Activities in Support Library 26.1.0 and later already implement the LifecycleOwner interface.
  3. Common implementation of lifecycle handling @Override public void onCreate(...) {

    myLocationListener = new MyLocationListener(this, (location) -> { // update UI }); } @Override public void onStart() { myLocationListener.start(); // manage other components that need to respond to the activity lifecycle } @Override public void onStop() { myLocationListener.stop(); // manage other components that need to respond to the activity lifecycle }
  4. Component can start before the activity is stopped class MyActivity

    extends AppCompatActivity { @Override public void onStart() { super.onStart(); Util.checkUserStatus(result -> { // what if this callback is invoked AFTER activity is stopped? if (result) { myLocationListener.start(); } }); }
  5. Lifecycle Defines an object that has an Android Lifecycle. Class

    that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.
  6. Lifecycle on location tracking example class MyActivity extends AppCompatActivity {

    private MyLocationListener myLocationListener; public void onCreate(...) { myLocationListener = new MyLocationListener(this, getLifecycle(), location -> { // update UI }); Util.checkUserStatus(result -> { if (result) { myLocationListener.enable(); } }); } }
  7. LifecycleObserver implementation class MyLocationListener implements LifecycleObserver { //Receive callbacks for

    Lifecycle events @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { if (enabled) { // connect } } public void enable() { enabled = true; //Query the current state of the Lifecycle if (lifecycle.getCurrentState().isAtLeast(STARTED)) { // connect if not connected } } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { // disconnect if connected } }
  8. DefaultLifecycleObserver and Java 8 class TestObserver implements DefaultLifecycleObserver { @Override

    public void onCreate(LifecycleOwner owner) { // your code } } public interface DefaultLifecycleObserver extends FullLifecycleObserver { //provides default implementation for all 6 FullLifecycleObserver methods @Override default void onCreate(@NonNull LifecycleOwner owner) { } } If you use Java 8 language, always prefer it over annotations.
  9. Implementing a custom LifecycleOwner public class MyActivity extends Activity implements

    LifecycleOwner { private LifecycleRegistry mLifecycleRegistry; @Override protected void onCreate(Bundle savedInstanceState) { mLifecycleRegistry = new LifecycleRegistry(this); mLifecycleRegistry.markState(Lifecycle.State.CREATED); } @Override public void onStart() { mLifecycleRegistry.markState(Lifecycle.State.STARTED); } @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; } }
  10. LiveData • Observable data holder class • Is lifecycle-aware •

    Only notifies active observers about updates • The Room persistence library supports observable queries, which return LiveData objects Observer • A simple callback that can receive from LiveData
  11. Work with LiveData • Create an instance of LiveData to

    hold a certain type of data. This is usually done within your ViewModel class • Create an Observer object that defines the onChanged() method (usually done in a UI controller, such as an activity or fragment) • Attach the Observer object to the LiveData object using the observe() method. The observe() method takes a LifecycleOwner object
  12. Create LiveData objects public class NameViewModel extends ViewModel { //

    Create a LiveData with a String private MutableLiveData<String> mCurrentName; public MutableLiveData<String> getCurrentName() { if (mCurrentName == null) { mCurrentName = new MutableLiveData<String>(); } return mCurrentName; } // Rest of the ViewModel... }
  13. Observe LiveData objects // Get the ViewModel viewModel = ViewModelProviders.of(this).get(NameViewModel.class);

    // Create the observer which updates the UI final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { // Update the UI, in this case, a TextView nameTextView.setText(newName); } }; // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer viewModel.getCurrentName().observe(this, nameObserver);
  14. Update LiveData objects button.setOnClickListener(new OnClickListener() { @Override public void onClick(View

    v) { String anotherName = "John Doe"; viewModel.getCurrentName().setValue(anotherName); } }); liveData.postValue("a"); //call it from a worker thread liveData.setValue("b"); //call it from a main thread
  15. Transforming LiveData • map() - apply function to change LiveData

    output • switchMap() - apply function that swaps LiveData observer it is listening to • MediatorLiveData - LiveData with multiple sources for custom transformations
  16. Transformations.map(...) Transformations.map() applies a function on a LiveData instance and

    dispatches the result to its observers, giving you the opportunity to manipulate the data value. LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
  17. Transformations.switchMap(...) Transformations.switchMap() applies a function to the value stored in

    the LiveData object. The function passed to switchMap() must return a LiveData object MutableLiveData<String> userIdLiveData = ...; LiveData<User> userLiveData = Transformations.switchMap(userIdLiveData, id -> repository.getUserById(id)); void setUserId(String userId) { this.userIdLiveData.setValue(userId); }
  18. ViewModel • Designed to hold data that is related to

    the UI • Allows data to survive configuration changes such as screen rotations • ViewModel objects are scoped to the Lifecycle
  19. Implement a ViewModel public class MyViewModel extends ViewModel { private

    MutableLiveData<List<User>> users; public LiveData<List<User>> getUsers() { if (users == null) { users = new MutableLiveData<List<Users>>(); loadUsers(); } return users; } private void loadUsers() { // Do an asyncronous operation to fetch users } }
  20. ViewModelProviders public class MyActivity extends AppCompatActivity { public void onCreate(Bundle

    savedInstanceState) { // Create a ViewModel the first time the system calls an activity's onCreate() method. // Re-created activities receive the same MyViewModel instance created by the first activity. MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class); viewModel.getUsers().observe(this, users -> { // update UI }); } }
  21. AndroidViewModel Caution: A ViewModel must never reference a View, Lifecycle,

    or any class that may hold a reference to the activity context. AndroidViewModel is Application context aware ViewModel AndroidViewModel subclasses must have a constructor which accepts Application as the only parameter.
  22. The lifecycle of a ViewModel ViewModel objects are scoped to

    the Lifecycle passed to the ViewModelProvider when getting the ViewModel.
  23. Share data between fragments public class SharedViewModel extends ViewModel {

    private final MutableLiveData<Item> selected = new MutableLiveData<Item>(); public void select(Item item) { selected.setValue(item); } public LiveData<Item> getSelected() { return selected; } } //Fragments can share a ViewModel using their activity scope SharedViewModel viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);