ViewModel/LiveData/LifeCycle使用

这几个库理论上应该都会使用, 我认为属于JetPack中的基础库, 早期称为ArchitectureComponent, 后被并入Jetpack组件库之中.php

androidx内置LiveData/ViewModel/Lifecycle, 无需导入依赖.html

  1. LiveData: 感知活跃(onStart)和非活跃状态(onPause)的数据观察者java

  2. ViewModel: 屏幕旋转自动保存数据, 或者意外销毁读写saveInstance数据android

  3. Lifecyle: 能够监听生命周期, 默认Activity和Fragment已经实现lifecyclegit

参考文献github

ViewModel

ViewModel只能在屏幕旋转时保存数据, 而没法在内存回收Activity时保存数据(除非使用SavedState)框架

ViewModel 用于继承实现自定义的数据实体

ViewModelStore 存储多个ViewModel的存储类, 开发者无需关心

ViewModelStoreOwner Fragment|Activity都属于其派生类. 在ViewModelProvider建立时使用.

ViewModelProvider 用于建立ViewModel

建立ViewModule

public class LiveDataTimerViewModel extends ViewModel {
  /**/ } 复制代码

使用

绑定生命周期同时返回一个ViewModel实例

ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory(application)).get(T::class.java) 复制代码

ViewModel有个覆写函数, 用于提供依附的ViewModelStoreOwner销毁是清理数据(设置对象为NULL/解绑监听器等)

protected void onCleared ()
复制代码

默认的AppCompatActivity就实现了LifeCycleOwnerViewModelStoreOwner

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, OnBackPressedDispatcherOwner { 
          //...
        }
复制代码

同时Fragment也实现了ViewModelStoreOwner

ViewModelStoreOwner

ViewModel绑定生命周期的对象必须实现ViewModelStoreOwner. 该接口的职责是保存ViewModelStore对象.

咱们能够经过实现该接口自定义

public interface ViewModelStoreOwner {
    /** * Returns owned {@link ViewModelStore} * * @return a {@code ViewModelStore} */
    @NonNull
    ViewModelStore getViewModelStore();
}
复制代码

ViewModelStore

能够看作一个HashMap集合存储ViewModel的类, 能够建立对象

public final void clear() // 会触发全部ViewModel对象的onClear函数. 该函数中通常用于ViewModel是否某些内存 复制代码

ViewModelProvider

ViewModel必须经过该类建立对象

val model = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get<Model>()
复制代码

构造函数

public ViewModelProvider (ViewModelStoreOwner owner, ViewModelProvider.Factory factory) public ViewModelProvider (ViewModelStore store, ViewModelProvider.Factory factory) 复制代码

使用方法

<T extends ViewModel> T get(Class<T> modelClass) <T extends ViewModel> T get(String key, Class<T> modelClass) 复制代码

ViewModel.Factory

该类用于覆写函数建立ViewModel的实例对象

查看默认的NewInstanceFactory源码能够看到

public static class NewInstanceFactory implements Factory {

  @SuppressWarnings("ClassNewInstance")
  @NonNull
  @Override
  public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
    //noinspection TryWithIdenticalCatches
    try {
      return modelClass.newInstance(); // 经过反射建立对象
    } catch (InstantiationException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    }
  }
}
复制代码

有时候你的数据属于网络请求过来的数据实体, 这个时候就须要用构造器来

AndroidViewModel

该类用于建立ViewModel实例的时候调用其构造函数(具有参数Application), 让ViewModel中可使用Application

查看源码:

@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
  if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
    //noinspection TryWithIdenticalCatches
    try {
      // 经过具有参数Applicaiton的构造函数使用反射建立对象
      return modelClass.getConstructor(Application.class).newInstance(mApplication); 

    } catch (NoSuchMethodException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    } catch (InstantiationException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException("Cannot create an instance of " + modelClass, e);
    }
  }
  return super.create(modelClass);
}
复制代码

onSaveInstanceState 和 ViewModel 区别

  • 须要序列化和反序列化, 占用空间大而且耗时
  • 主线程处理
  • 进程死亡也能够不影响

Saved State

ViewModel本质上和onSaveIntance有区别.

  1. ViewModel能够保存复杂大量数据, onSaveIntance基于Bundle对象保存不能存储大量数据(抛出异常)

  2. ViewModel没法在乎外销毁时恢复数据, 只是配置变动(切换横竖屏)时数据依然存在

须要额外扩展依赖

implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha05'
复制代码

绑定全部者的时候使用SavedStateVMFactory工厂实例

mSavedStateViewModel = ViewModelProviders.of(this, new SavedStateVMFactory(this))
                .get(SavedStateViewModel.class);
复制代码

ViewModel须要建立一个构造函数

public class SavedStateViewModel extends ViewModel {
  
  // 自定义的构造函数
    public SavedStateViewModel(SavedStateHandle savedStateHandle) {
        mState = savedStateHandle; // mState便可以读写数据, 不须要你去处理生命周期
    }
}
复制代码

SavedStateHandle可以保存和查询数据. 数据会和onSaveInstanse保存机制同样不会丢失.

public <T> MutableLiveData<T> getLiveData(@Nullable String key) 

public Set<String> keys()

public <T> T get(@NonNull String key) 

public <T> void set(@NonNull String key, @Nullable T value)

public boolean contains(@NonNull String key)

public <T> T remove(@NonNull String key)
复制代码

扩展

个人开源框架Net框架支持快速建立ViewModel

val model = getViewModel<Model>() // 仅仅配置变动数据恢复的

val model = getSavedModel<Model>() // 支持onSaveIntance意外销毁恢复数据的
复制代码

Model

class Model(saved: SavedStateHandle) : SavedViewModel(saved) {
    var name: String?
        get() = saved.get("name")
        set(value) {
            saved["name"] = value
        }
}
复制代码
  1. 提供一个SavedViewModel类用于快速继承, saved即用于保存和恢复数据的存储对象

  2. 若是不想介入Net, 能够参考源码

    open class SavedViewModel(var saved: SavedStateHandle) : ViewModel()
    
    inline fun <reified M : ViewModel> ViewModelStoreOwner.getViewModel(): M {
        return ViewModelProvider(this).get(M::class.java)
    }
    
    inline fun <reified M : ViewModel> FragmentActivity.getSavedModel(): M {
        return ViewModelProvider(
            this,
            SavedStateViewModelFactory(application, this)
        ).get(M::class.java)
    }
    
    
    inline fun <reified M : ViewModel> Fragment.getSavedModel(): M {
        return ViewModelProvider(
            this,
            SavedStateViewModelFactory(activity!!.application, this)
        ).get(M::class.java)
    }
    复制代码

LiveData

使数据变成一个可被观察状态, 而且符合视图的生命周期.

在活跃状态观察者能够接受到事件, 不活跃状态观察者不会接收到事件. 若是生命周期全部者被破坏自动删除观察者.

活跃状态即非onPause或者onDestroy

  1. 添加已被销毁的生命周期全部者, 会忽略
  2. 添加已经被添加过的生命周期全部者也会忽略
  3. 若是观察者已经被另外一个liveData添加过, 会抛出IllegalArgumentException

继承关系

java.lang.Object
   ↳	androidx.lifecycle.LiveData<T>
 	   ↳	androidx.lifecycle.MutableLiveData<T>
 	 	   ↳	androidx.lifecycle.MediatorLiveData<T>
复制代码

所有公开方法

T getValue() // 返回当前值 boolean hasActiveObservers() // 是否有被激活的观察者(处于活跃状态) boolean hasObservers() // 是否有观察者 void observe(LifecycleOwner owner, Observer<T> observer) void observeForever(Observer<T> observer) // 添加一个永远处于活跃状态的观察者(而且不会自动删除观察者), 因此须要你本身删除观察者 // 重复添加同一个观察者会抛出IllegalArgumentException void removeObserver(Observer<T> observer) // 删除观察者 void removeObservers(LifecycleOwner owner) // 删除拥有同一个生命周期全部者的全部观察者 复制代码

提供覆写函数

protected void onInactive ()

protected void onActive ()

protected void postValue (T value)

protected void setValue (T value)
复制代码

这是一个抽象类, 咱们通常都是用他的子类MutableLiveData<T>

建立MutableLiveData

// 建立对象
var data = MutableLiveData<String>()

// 设置值
data.value = "设计师"

// 设置观察者
data.observe(this@MainActivity, Observer {
    Log.d("日志", "(MainActivity.kt:28) ___ it = $it")
  })
复制代码
  • AppCompatActivity自己就是实现了LifeCycleOwner因此我这里直接传入This

在数据变化后调用方法设置值(根据所处线程不一样而调用不一样的方法)

// 主线程
data.value = "设计师"

// 异步线程
data.postValue("设计师")
复制代码

若是在观察者以前设置值则设置观察者以后会受到你设置以前最后一次设置的值, 注意最后一次.

MutableLiveData

这个继承自liveData(abstract). 只是public两个私有方法(原本是protected)

所有源码:

public class MutableLiveData<T> extends LiveData<T> {
  
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
复制代码

LiveData能够存在多个观察者

自定义LiveData

咱们能够模仿MutableLiveData 本身自定义LiveData的逻辑

public class MyLiveData extends LiveData<String> {
  /** * 活跃状态 */
  @Override protected void onActive() {
    super.onActive();
  }

  /** * 非活跃状态 */
  @Override protected void onInactive() {
    super.onInactive();
  }
}
复制代码

要想触发这两个方法必需要绑定观察者.

其实实现LifecycleObserver自己也可以实现生命周期的回调.

可是LiveData能够能够监听值变化 (其实Kotlin也能)而且根据生命周期自动取消观察者.

Transformations

Transformations 提供两个函数, 他的功能相似RxJava的mapflatMap操做符, 转换LiveData的数据.

static <X, Y> LiveData<Y> map(LiveData<X> source, Function<X, Y> func) static <X, Y> LiveData<Y> switchMap(LiveData<X> trigger, Function<X, LiveData<Y>> func) 复制代码

map示例:

final MyLiveData myLiveData = new MyLiveData();

    myLiveData.observe(this, new Observer<String>() {
      @Override public void onChanged(@Nullable String s) {
      }
    });

    final LiveData<Integer> transformationLiveData =
        Transformations.map(myLiveData, new Function<String, Integer>() {
          /** * 若是想要该方法回调须要结果LiveData设置观察者才行 * * @param input 源LiveData存储的数据 * @return 最终返回的LiveData存储的数据 */
          @Override public Integer apply(String input) {
            return 2;
          }
        });

    transformationLiveData.observe(this, new Observer<Integer>() {
      @Override public void onChanged(@Nullable Integer integer) {
        
      }
    });
复制代码

switchMap示例

final LiveData<Integer> transformationLiveData =
  Transformations.switchMap(myLiveData, new Function<String, LiveData<Integer>>() {
    /** * @param input 源数据 * @return 返回结果等于switchMap的结果 */
    @Override public LiveData<Integer> apply(String input) {
      MutableLiveData<Integer> transformationLiveData = new MutableLiveData<>();
      transformationLiveData.setValue(3);
      return transformationLiveData;
    }
  });
复制代码

总结:

二者区别即map返回的是一个类型, 而switchMap规定返回的是一个新的LiveData.

能够看作map能够替代switchMap, 由于MutableLiveData也是一个类型.

做为Transformation的参数传进去的LiveData若是以前就设置过Observer一样会生效, 至关于有两个观察者.

MediatorLiveData

能够设置多个源LiveData. 而后经过观察者来同时监听多个LiveData的变化

MediatorLiveData自己也是LiveData的一部分

<S> void addSource(LiveData<S> source, Observer<S> onChanged) // 添加源 <S> void removeSource(LiveData<S> toRemote) // 删除源 复制代码

示例

var data = MutableLiveData<String>()
var data2 = MutableLiveData<Int>()

// 这里就是在data,data2变动值时通知MediatorLiveData也更新
mediatorLiveData.addSource(data, Observer { mediatorLiveData.value = 1 })
mediatorLiveData.addSource(data2, Observer { mediatorLiveData.value = 3 })

mediatorLiveData.observe(this, Observer {
	// data或data2属性变化都会在这里被监听
})
复制代码

结合Databinding

关于LiveData的应用我认为只是针对应用后台和前台展现的应用场景

LiveData实现MVVM

有些人可能会说用LiveData来写MVVM, 可是我以为这有点扯淡了, LiveData只会在赋值对象的时候才会通知监听器, 对象中的属性变化并不会.

并且就算你为每一个数据都用LiveData写个监听器那也得在监听器中绑定UI, 这和本身每次设置UI有什么区别.

若是是对于ui的更新仍是推荐使用Databinding的数据绑定形式, 能够结合LiveData实现前台更新数据

binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, layout)
binding.lifecycleOwner = this
binding.m = model
复制代码

Model

class Model{
    val data = MutableLiveData<String>()
}
复制代码

XML

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable name="m" type="com.example.architecture.Model" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">

        <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{m.data}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
复制代码

这样Databinding更新属性就会具有LiveData的感知生命周期的功能, 只有处于前台才会当即更新ui.

ObservableLiveData区别

  • LiveData 能够延期执行(等待活跃状态)
  • Observable 双向数据绑定, LiveData只能单向数据观察者
  • Observable监听器若是不是绑定ui没法保证ui没有销毁

liveData还拥有官方的协程扩展库, 能够建立具有活跃状态的协程的做用域, 具体请查看个人协程文章: Kotlin协程: Coroutine/Channel/Flow 以及实际应用

Lifecycle

生命周期组件, 能够将一个类赋予Activity生命周期.

使用

实现接口LifecycleObserver

public class CusLifecycleObserver implements LifecycleObserver {}
复制代码

绑定生命周期

lifecycleOwner.getLifecycle().addObserver(this);
复制代码

而后就能够经过注解来在生命周期时自动调用

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void removeLocationListener() {
            if (mLocationManager == null) {
                return;
            }
            mLocationManager.removeUpdates(mListener);
            mLocationManager = null;
            Log.i("日志", "(BoundLocationListener.java:74) ___ removeLocationListener");
        }
    }
复制代码

全部的生命周期状态

public enum Event {
      
        ON_CREATE,
        
        ON_START,
       
        ON_RESUME,
        
        ON_PAUSE,
        
        ON_STOP,
        
        ON_DESTROY,
        
        ON_ANY
    }
复制代码

执行顺序

若是你想自定义LifecycleOwner也能够

public class MyActivity extends Activity implements LifecycleOwner {
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        mLifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return  new LifecycleRegistry(this);
    }
}
复制代码

这里我继承是Activity, 并不表明生命周期就只能是Activity的, 能够是任何具备生命周期的组件(官方同时支持Service的生命周期).

LifecycleOwner

只有一个函数

public abstract Lifecycle getLifecycle ()
复制代码

LifecycleRegistry

这是控制生命周期状态变动的控制器

public void addObserver (LifecycleObserver observer) // 添加观察者 public void removeObserver (LifecycleObserver observer) // 删除观察者 public int getObserverCount () // 当前观察者数量 public Lifecycle.State getCurrentState () // 当前状态 public void markState (Lifecycle.State state) // 设置当前状态, 通常用户自定义LifecycleOwner使用 public void handleLifecycleEvent (Lifecycle.Event event) // 设置当前状态, 和markState不一样是这个若是参数状态和当前状态一直不会通知Observer观察者 复制代码

Lifecycle.State

有五种状态

Lifecycle.State 	CREATED

Lifecycle.State 	DESTROYED

Lifecycle.State 	INITIALIZED
. 
Lifecycle.State 	RESUMED

Lifecycle.State 	STARTED
复制代码
public boolean isAtLeast (Lifecycle.State state) // 若是当前声明周期大于等于参数生命周期则返回true public static Lifecycle.State valueOf (String name) // 将字符串转为State 复制代码

生命周期监听

只能有一个或者没有参数, 可是能够增长一个LifecycleOwner参数. 而且ON_ANY注解的方法能够增长第二个注解Event. 该参数的做用只是判断当前所处的生命周期.

class TestObserver implements LifecycleObserver {
   
   @OnLifecycleEvent(ON_CREATE)
   void onCreated(LifecycleOwner source) {}

   @OnLifecycleEvent(ON_ANY)
   void onAny(LifecycleOwner source, Event event) {}
 }
复制代码

生命周期覆写函数

上面提到了用注解来控制生命周期, 若是你当前使用的JDK是JDK8以上能够选择覆写函数的形式来回调生命周期

不太推荐感受冗余

须要另外导入一个依赖:

dependencies {
    // Java8 support for Lifecycles
    implementation "android.arch.lifecycle:common-java8:1.0.0"
}

复制代码

而且再也不使用注解而是使用重写方法, 而且实现DefaultLifecycleObserver

class TestObserver implements DefaultLifecycleObserver {
     @Override
     public void onCreate(LifecycleOwner owner) {
         // your code
     }
 }
复制代码
相关文章
相关标签/搜索