android-lifecycle筆記

ViewModel

ViewModel的職責是爲Activity或者Fragment管理數據.java

如何獲取一個ViewModel?

  1. 繼承ViewModel或者AndroidViewModel
class MyViewModel : ViewModel(){
     
 }
 
 //若是你須要在ViewModel中使用上下文對象,能夠繼承AndroidViewModel
class MyViewModel2(var application : Application) : AndroidViewModel(){
    
}
若是繼承 AndroidViewModel,構造函數必須有一個 Application類型的參數,而且只能是 Application,而不是其子類.
  1. Activity或者Fragment中獲取MyViewModel實例對象
val myViewModel = ViewModelProviders.of(activity/fragment).get(MyViewModel::class.java)

ViewModel的惟一性

  1. 若是一個Activity/Fragment未被銷燬,那麼屢次獲取ViewModel,獲得的是同一個實例對象.
    從源碼中去分析這個邏輯.
    先看ViewModelPoviders.of()這個方法,返回一個ViewModelProvider對象
public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }
    
    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }

這裏只看Activity的android

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);
    }

看一下ViewModelProvider這個構造函數架構

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

當獲取到ViewModelProvider對象後,調用其get方法獲取到MyViewModel的實例對象
看一下get方法app

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) {
     //從ViewModelStore中獲取ViewModel對象
        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;
    }

從這裏能夠看到是從ViewModelStore中獲取ViewModel對象.在ViewModelStore中封裝了一個HashMap對象.若是HashMap對象中存儲了ViewModel對象,就直接複用,若是ViewModel對象未建立,就從新建立後存儲在HashMap中.ide

要保證ViewModel是惟一的,ViewModelStore就必須是惟一的.看一下ViewModelStore是若是獲取到的.
在給ViewModelProvider傳參數時調用了ViewModelStores.of(activity),看一下這一步作了什麼?函數

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

查看安卓源碼發現,support包下的Fragment和FragmentActivity都繼承了ViewModelStoreOwner,天然要實現其方法.post

//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;
        }
    }

能夠看出,對於一個未銷燬的Activity或者Fragment,其ViewModelStore對象是惟一的.那麼其存儲的ViewModel對象也是惟一的.this

ViewModel的特色

由上面可知,Activity或者Fragment未被銷燬,ViewModel是惟一的,那麼其保存的數據也是不變的,當Activity發生了屏幕旋轉等變化時,仍舊能夠複用ViewModel中的數據.google

不要持有View層的引用

ViewModel內部不要持有View層的引用,好比Activity或者Fragment.能夠和LiveData結合使用spa

生命週期

ViewModel生命週期

由圖可看出,Activity重建先後,ViewModel保持不變.

LiveData

LiveData持有數據,並可在給定的生命週期內被觀測.
繼承關係以下:
[LiveData] ^- [MutableLiveData] ^- [MediatorLiveData]

MutableLiveData對外暴露setValuepostValue.
MediatorLiveData觀察別的LiveData.並能將active/inactive狀態傳遞給它所觀察的LiveData對象.

postValue與setValue

postValue能夠從後臺線程更新數據,setValue只能在主線程中更新數據.若是同時調用這兩個方法,postValue設置的數據會覆蓋code>setValue設置的數據.postValue是經過ArchTaskExecutor來實如今主線程中更新數據.在ArchTaskExecutor中使用主線程的Handler.

observeForever與removeObserver

若是一個觀察者經過observeForever被添加,這個觀察者會被認爲一直處於激活狀態,任何數據更新都會當即通知到它.所以須要手動調用removeObserver去移除它.

onActive與onInactive

Lifecycle

v4包下的SupportActivityFragment默認都實現了LifecycleOwner(<font color='#ff0000' size='6px'>API27+</font>),而且都默認初始化了lifeCycle實例

//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

若是你使用的是java8,能夠經過添加如下依賴來使用DefaultLifecycleObserver

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

而後實現DefaultLifecycleObserver

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

若是使用的是java7,經過註解來監聽生命週期事件.而且能夠給對用的生命週期方法添加一個LifecycleOwner參數.若是方法被Lifecycle.Event.ON_ANY註解,那麼該方法能夠額外添加一個Lifecycle.Event.ON_ANY參數.

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

google官方MVVM架構圖

由圖能夠看出,無論數據從哪裏來,最終要匯聚到數據倉庫,LiveData觀察的是數據倉庫的變化.而且ViewModel中能夠定義多個LiveData.

相關文章
相關標籤/搜索