Android Architecture Components

Android Architecture Components是Google为开发者提供的架构设计方案,里面包含若干内容:

  • Lifecycle
  • ViewModel
  • LiveData
  • Room
  • Paging

具体介绍和教程见官网,暂时项目用得上是前三个,重点吹吹ViewModel和LiveData。Room是官方提供的对SQLite的抽象,知道它的存在就好,没有找到取代greenDAO或者realm的理由。Paging支持对RecyclerView分页加载,可以期待,但现在版本还是1.0.0rc,先放一边。

现在最新的版本:android.arch.lifecycle:extensions:1.1.1

Lifecycle

向上找Activity的父类,在SupportActivity里实现了LifecycleOwner,里面只有一个方法getLifecycle。(某个版本api添加的哈,人懒没有去查是几)

在onCreate可以将Activity的生命周期委托给LifecycleObserver:

lifecycle.addObserver(MyLifecycleObserver())

LifecycleObserver是一个接口,我们使用@OnLifecycleEvent绑定生命周期和具体的函数。除了ON_CREATE等基本的,还添加了ON_ANY。

class MyLifecycleObserver : LifecycleObserver {
    companion object {
        val LIFECYCLE_TAG = TAG + "lifecycle"
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        LogUtils.d("$LIFECYCLE_TAG-onCreate")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        LogUtils.d("$LIFECYCLE_TAG-onStart")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    fun onAny() {
        //LogUtils.d("$LIFECYCLE_TAG-onAny")
    }
}

使用Lifecycle好处显而易见,Activity生命周期的函数不用散落到各处,可以统一在一个地方处理好。

ViewModel和LiveData

ViewModel就是MVVM模式中的VM,默认你认识MVVM和databinding,写个demo。

Android Architecture Components_第1张图片
photo

Activity里有两个Fragment(红色是Fragment1、蓝色是Fragment2),通过“上一页”、“下一页”切换。有一个持久化的user对象,包括“name”和“age”两个属性,点击按钮“更新user”,变更user对象的属性并显示在两个Fragment中。

功能很简单,但是需要处理常见的Fragment间通信。假如使用MVP模式,每个Fragment对应一个Presenter。两个Fragment之间的通信,要不使用Activity传递参数,要不使用RxBus之类的事件总线,ViewModel提供更简单的方法。

首先介绍LiveData,可以包装任意类型的对象,它有三个特点:

  • 供观察者订阅
  • 感知组件(Activity、Fragment、Service)生命周期
  • 提供活跃状态,活跃的才通知观察者

在ViewModel自定义一个init函数,创建User对象的LiveData:

private lateinit var userData: LiveData

fun init() {
    val user = createUser()
    this.userData = userRepository.getUser(user.userId)
}

userRepository是M层的对象,我这里使用了ROOM,它可以直接返回对象的LiveData。如果是其他持久化库,返回的user对象可以手动setValue进MutableLiveData。MutableLiveData是LiveData的子类,可以修改值,还有一个子类MediatorLiveData,可以观测一个或多个LiveData的变化,用到再说了。

更新值有两个方法,一个是postValue,一个是setValue。前者可以在任意线程,后者只能在主线程。


在Activity里获取ViewModel:

val viewModel = ViewModelProviders.of(this).get(PersonalDetailViewModel::class.java)

在Fragment里获取ViewModel:

val viewModel = ViewModelProviders.of(activity!!).get(PersonalDetailViewModel::class.java)

两者非常相似,要注意of函数传入的参数,无论是Activity还是Fragment,都是传入activity对象,这样保证它们获取同一个ViewModel。(Activity里有个Map保存ViewModel)


viewModel.getUserData().observe(this, Observer { user ->
    user?.let {
        tv_name.text = user.name
        tv_age.text = user.age.toString()
    }
})

在Fragment2中通过observe订阅LiveData变化,当Fragment1修改User属性,Fragment2触发Observer的onChanged函数,我们对应修改ui显示。只要订阅了LiveData,任意地方都可以即时知道。

既然有订阅观察,为什么没有写对应的解绑订阅?这就是LiveData的第二个特点,注意到observe传入的参数是LifecycleOwner,它是可以感知组件的生命周期。当生命周期是DESTORY时,自动解绑订阅,具体后面分析源码就知道了。

也有另外一个observeForever函数,不需要传入LifecycleOwner,但是需要手动使用remove,和普通的观察者模式一样。

还有第三个特点,活跃状态。这个很好理解,组件处于某些状态时,才通知观察者变化。

LiveData源码分析

知其然知其所以然,顺手看看ViewModel和LiveData的实现方式。

LiveData是典型的观察者模式,使用自定义的SafeIterableMap保存所有观察者。

private SafeIterableMap, ObserverWrapper> mObservers = new SafeIterableMap<>();

键值对类型, ObserverWrapper>,Observer是观察者对象,ObserverWrapper是什么东西,观察者的包装类?

private abstract class ObserverWrapper {
    final Observer mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    //...
}

果然ObserverWrapper包装了Observer,增加了active和version。LifecycleBoundObserver是ObserverWrapper的抽象实现类,包含了生命周期LifecycleOwner。他们的联系很清楚了,对Observer的管理叠加了生命周期,看LifecycleBoundObserver其中两个函数:

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

    //...

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    //...
}

当生命周期变为DESTROYED时,自动移除观察者,实现上节所讲感知组件生命周期。当组件处于活跃时,观察才是有效的,这里需要生命周期至少是STARTED。最后调用ObserverWrapper.activeStateChanged处理生命周期变化。

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    mActive = newActive;
    boolean wasInactive = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;
    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    if (mActive) {
        dispatchingValue(this);
    }
}

onActive和onInactive是两个空函数,可以让LiveData的子类额外处理活跃变化。处于活跃时,调用dispatchingValue通知观察者。具体的通知过程路过,不外乎是循环所有观察者,根据条件调用onChange函数。

最后看回LiveData的订阅函数observe,有了上面的分析,都不用讲了。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);
}

ViewModel源码分析

ViewModel是一个抽象类,里面只有一个clear函数,需要时可以重写做些清理。

public abstract class ViewModel {
    protected void onCleared() {
    }
}

使用ViewModel的入口函数在ViewModelProviders,核心是函数of,区分入参Fragment和Activity两个版本。

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

of返回的对象是ViewModelProvider,和ViewModelProviders差了个s。

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

创建ViewModelProvider需要两个对象:

  • ViewModelStore
  • Factory
Factory
public interface Factory {
    @NonNull
     T create(@NonNull Class modelClass);
}

Factory接口,只有一个函数create,传入class,创建ViewModel。AndroidViewModelFactory是它的实现类:

//AndroidViewModelFactory
@NonNull
@Override
public  T create(@NonNull Class modelClass) {
    if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
        //noinspection TryWithIdenticalCatches
        try {
            return modelClass.getConstructor(Application.class).newInstance(mApplication);
        } 
       //catch...
    }
    return super.create(modelClass);
}

通过isAssignableFrom判断class类型是不是AndroidViewModel,是的话创建带Application实例的AndroidViewModel。不是的话,创建工作交给父类NewInstanceFactory,对应的create函数创建无参构造函数的普通ViewModel。

//NewInstanceFactory
public  T create(@NonNull Class modelClass) {
    //noinspection TryWithIdenticalCatches
    try {
        return modelClass.newInstance();
    } 
    //catch...
}
ViewModelStore
private final HashMap mMap = new HashMap<>();

ViewModelStore很简单,里面有一个HashMap,保存key和ViewModel。很明显它是ViewModel的缓存,可以使用get和put操作。

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

ViewModelStore通过调用ViewModelStores.of获取,有两种获取来源:

  • 第一种,ViewModelStore对象保存在Activity和Fragment,它们都实现了ViewModelStoreOwner接口。因此,可以很轻松在Activity或Fragment得到我们需要的ViewModel对象。
  • 第二种,ViewModelStoreOwner接口是某个时候加入Activity的,如果之前的没有实现接口又怎样办?

大神们弄了个HolderFragment承载ViewModelStore:

HolderFragment holderFragmentFor(FragmentActivity activity) {
    FragmentManager fm = activity.getSupportFragmentManager();
    HolderFragment holder = findHolderFragment(fm);
    if (holder != null) {
        return holder;
    }
    holder = mNotCommittedActivityHolders.get(activity);
    if (holder != null) {
        return holder;
    }

    if (!mActivityCallbacksIsAdded) {
        mActivityCallbacksIsAdded = true;
        activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
    }
    holder = createHolderFragment(fm);
    mNotCommittedActivityHolders.put(activity, holder);
    return holder;
}

就是这个方法createHolderFragment,动态将HolderFragment添加进Activity,然后就可以获取ViewModelStore了。

private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
    HolderFragment holder = new HolderFragment();
    fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
    return holder;
}

Fragment里添加HolderFragment类似,用的是ChildFragmentManager。

ViewModelProvider.get()

最后一步,从ViewModelProvider获取ViewModel的get函数:

@NonNull
@MainThread
public  T get(@NonNull Class 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);
}

@NonNull
@MainThread
public  T get(@NonNull String key, @NonNull Class modelClass) {
    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;
}

ViewModel存在于ViewModelStore时直接获取,否则创建并加入ViewModelStore,key的构成是固定字符串加上类的canonicalName。

总结

可以用

你可能感兴趣的:(Android Architecture Components)