Android lifecycle notes

Time:2019-12-10

ViewModel

ViewModelThe job is toActivityperhapsFragmentManage data

How to get a ViewModel?

  1. inheritViewModelperhapsAndroidViewModel
class MyViewModel : ViewModel(){
     
 }
 
 //If you need to use context objects in ViewModel, you can inherit Android ViewModel
class MyViewModel2(var application : Application) : AndroidViewModel(){
    
}

If inheritanceAndroidViewModel, constructor must have oneApplicationParameter of type and can only beApplication, instead of its subclass

  1. stayActivityperhapsFragmentGet inMyViewModelInstance object
 val myViewModel = ViewModelProviders.of(activity/fragment).get(MyViewModel::class.java)

Uniqueness of ViewModel

  1. If an activity / fragment is not destroyed, the ViewModel will be obtained multiple times and the same instance object will be obtained
    Analyze this logic from the source code
    First, look at the method viewmodelproviders. Of (), which returns a viewmodelprovider object
    public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }
    
    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }

This is only for activity

     public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        Application application = checkApplication(activity);
        if (factory == null) {
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return new ViewModelProvider(ViewModelStores.of(activity), factory);
    }

Take a look at the viewmodelprovider constructor

  public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        this.mViewModelStore = store;
    }

After getting the viewmodelprovider object, call its get method to get the instance object of myviewmodel
Take a look at the get method

public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    
    
     public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
     //Get the ViewModel object from the viewmodelstore
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }

        viewModel = mFactory.create(modelClass);
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }

It can be seen from this that the ViewModel object is obtained from the viewmodelstore. A HashMap object is encapsulated in the viewmodelstore. If the ViewModel object is stored in the HashMap object, it will be reused directly. If the ViewModel object is not created, it will be re created and stored in the HashMap

To ensure that the ViewModel is unique, the viewmodelstore must be unique
When passing parameters to viewmodelprovider, viewmodelstores.of (activity) was called. What did you do in this step?

//ViewModelStores.java
public static ViewModelStore of(@NonNull FragmentActivity activity) {
        if (activity instanceof ViewModelStoreOwner) {
            return ((ViewModelStoreOwner) activity).getViewModelStore();
        }
        return holderFragmentFor(activity).getViewModelStore();
    }

Looking at the Android source code, we found that both fragment and fragment activity under the support package inherit viewmodelstoreowner, and naturally implement its methods

    //FragmentActivity
     public ViewModelStore getViewModelStore() {
        if (this.getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
        } else {
            if (this.mViewModelStore == null) {
                FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
                if (nc != null) {
                    this.mViewModelStore = nc.viewModelStore;
                }

                if (this.mViewModelStore == null) {
                    this.mViewModelStore = new ViewModelStore();
                }
            }

            return this.mViewModelStore;
        }
    }

It can be seen that for an undeleted activity or fragment, its viewmodelstore object is unique. Then its stored ViewModel object is also unique

Features of ViewModel

It can be seen from the above that if the activity or fragment is not destroyed and ViewModel is unique, then the saved data will remain the same. When the activity changes such as screen rotation, the data in ViewModel can still be reused

Do not hold references to view layers

Do not hold inside ViewModelViewReferences to layers, such asActivityperhapsFragmentYes. Yes.LiveDataCombined use

life cycle

Android lifecycle notes

As can be seen from the figure, ViewModel remains unchanged before and after activity reconstruction

LiveData

LiveDataHolds data and can be observed over a given life cycle
The inheritance relationship is as follows:
[LiveData] ^- [MutableLiveData] ^- [MediatorLiveData]

MutableLiveDataExternal exposuresetValueandpostValue.
MediatorLiveDataObserve otherLiveDataAnd will be able toactive/inactiveThe state is passed to what it observesLiveDataObject.

Postvalue and setValue

postValueYou can update data from a background thread,setValueData can only be updated in the main thread. If both methods are called at the same time,postValueThe data set will overwrite the data set by code > setValuepostValueIt is throughArchTaskExecutorTo update the data in the main threadArchTaskExecutorUsing theHandler.

Observeforever and removeobserver

If an observer passesobserveForeverIf it is added, the observer will be considered to be always active, and any data update will be immediately notified to it. Therefore, it needs to be called manuallyremoveObserverTo remove it

Onactive and oninactive

Lifecycle

Under the V4 package.SupportActivityandFragmentBy default, the lifecycleowner is implemented (< font color = ‘ාff0000’ size =’6px ‘> api27 + < / font >), and the lifecycle instance is initialized by default

  //LifecycleOwner
  public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

//supportActivity
public class SupportActivity extends Activity implements LifecycleOwner, Component {
   
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
      public Lifecycle getLifecycle() {
        return this.mLifecycleRegistry;
    }
}



public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner {
         LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

public class LifecycleRegistry extends Lifecycle {
 //.........
}

LifecycleObserver

If you are using java8, you can use it by adding the following dependenciesDefaultLifecycleObserver

android.arch.lifecycle:common-java8:<version>

Then realizeDefaultLifecycleObserver

 class TestObserver implements DefaultLifecycleObserver {
     @Override
     public void onCreate(LifecycleOwner owner) {
          // your code
      }
  }

If you are using java7, you can listen for lifecycle events through annotations, and you can add aLifecycleOwnerParameter. If the method isLifecycle.Event.ON_ANYAnnotation, then the method can add an additionalLifecycle.Event.ON_ANYParameters.

 class TestObserver implements LifecycleObserver {
     @OnLifecycleEvent(ON_CREATE)
    void onCreated(LifecycleOwner source) {}
     @OnLifecycleEvent(ON_ANY)
    void onAny(LifecycleOwner source, Event event) {}
  }

Google official MVVM architecture

It can be seen from the figure that no matter where the data comes from, it will eventually converge to the data warehouse,LiveDataWhat we observe is the change of data warehouse. AndViewModelMultiple can be defined inLiveData.