JetPack学习

108 阅读6分钟

原文Android业务架构 · 基础篇 · Jetpack四件套 - 掘金 (juejin.cn)

一、Lifecycle

在最近的更新中,不建议直接使用LifecycleObserver,之前可以直接使用此接口,定义一个类去实现它,然后写几个方法,并使用 @OnLifecycleEvent 注解标注该方法在哪一个生命周期使用

@OnLifecycleEvent(Lifecycle.Event.ON_START)
private fun stopTimer() {
    handler?.removeCallbacksAndMessages(null)
    handler = null
}

推荐使用 LifecycleEventObserver或者DefaultLifecycleObserver

/**
 * Marks a class as a LifecycleObserver. Don't use this interface directly. Instead implement either
 * {@link DefaultLifecycleObserver} or {@link LifecycleEventObserver} to be notified about
 * lifecycle events.
 *
 * @see Lifecycle Lifecycle - for samples and usage patterns.
 */
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {

}

使用LifecycleEventObserver

class Timer : LifecycleEventObserver {
    private var handler: Handler? = null
    private var seconds = 0
    private val TAG = "Timer"

    private fun startTimer() {
        handler = Handler(Looper.myLooper()!!)

        handler?.post(object : Runnable {
            override fun run() {
                Log.d(TAG, "Seconds: $seconds")
                seconds++
                handler?.postDelayed(this, 1000)
            }
        })
    }

    private fun stopTimer() {
        handler?.removeCallbacksAndMessages(null)
        handler = null
    }

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        when (event) {
            Lifecycle.Event.ON_START -> startTimer()
            Lifecycle.Event.ON_STOP -> stopTimer()
            else -> {}
        }
    }
}

主要重写 onStateChanged 方法,比如 ON_STAT,对应的就是activity或者fragment的create。

使用 DefaultLifecycleObserver

实现DefaultLifecycleObserver接口,根据需要去重写onCreate等方法即可。

最后在activity中注册

//添加observer
lifecycle.addObserver(Timer())

Lifecycle如何与Activity、Fragment关联起来的

核心主要是LifecycleOwnerLifecycleRegistryLifecycleLifecycleObserver

Lifecycle

抽象类,主要定义了一些用于标识生命的状态和事件。

    //添加观察者
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);
    //移除观察者
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    //获取当前状态
    public abstract State getCurrentState();

    //生命周期事件,对应Activity生命周期方法
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY  //可以响应任意一个事件`
    }
    //生命周期状态. (Event是进入这种状态的事件) 
    public enum State { 
        DESTROYED, 
        INITIALIZED, 
        CREATED, 
        STARTED, 
        RESUMED; 
        //判断至少是某一状态 
        public boolean isAtLeast(@NonNull State state) { 
            return compareTo(state) >= 0; 
        } 
    }

LifecycleRegistry继承Lifecycle,构造方法有以下几个。

public LifecycleRegistry(@NonNull LifecycleOwner provider) {
    this(provider, true);
}

private LifecycleRegistry(@NonNull LifecycleOwner provider, boolean enforceMainThread) {
    mLifecycleOwner = new WeakReference<>(provider);
    mState = INITIALIZED;
    mEnforceMainThread = enforceMainThread;
}

都会传入一个LifecycleOwner,就是生命周期持有者,一般是activity或者fragment,它们都会实现LifecycleOwner接口,重写getLifecycle方法,重写的方法都会返回一个LifecycleRegistry实例。

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}
  1. 对于fragment,直接在Fragment类中实现此接口。
  2. 对于Activity,它的继承关系主要由AppCompatActivity-> FragmentActivity -> ComponentActivity,在ComponentActivity中实现此接口。

即activity和fragment中都会实现lifecycleOwner接口,返回一个lifecycleRegistry实例,并且各自在实例化lifecycleRegistry时,都会传入this即当前的activity。

ComponentActivity

//分发生命周期事件
ReportFragment.injectIfNeededIn(this);

在每个生命周期中,通过LifecycleRegistry的handleLifecycleEvent方法来处理,移动到下一个生命周期,比如 onPause,此方法就传入Lifecycle.Event.ON_PAUSE,再调用moveToState,转向对应的状态,主要通过sync方法。

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                + "garbage collected. It is too late to change lifecycle state.");
    }
    while (!isSynced()) {
        mNewEventOccurred = false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

isSynced()主要判断mObservermap(用于存储LifecycleObserver对象和其关联的EventObserver对象。)中新旧的state是否相等,不相等的话,就进行转移,通过判断mState和mObservermap新旧状态,决定执行forward还是backwardpass。

二、LiveDta

观察者注册

通过observe方法添加。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    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);
}

通过addObserver(wrapper)注册观察者,传入LifecycleBoundObserver类型的wrapper。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver

观察者解注册

主要通过 removeObservers 方法,会遍历观察者列表,从中删除对应的观察者。

数据更新

setValue

在主线程中进行调用的,它会直接更新LiveData中的数据并通知所有的观察者进行UI更新;

protected void setValue(T value) {
    ...
    dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
    ...
    observer.mObserver.onChanged((T) mData);
}

最终回调到OnChanged,更新数据。

postValue

在异步线程中进行调用的,它会将要更新的数据封装成PendingPost对象,并提交给主线程的Handler进行处理,最终还是会调用到setValue.

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

三、ViewModel

是一个以生命周期感知的方式来保存和管理UI相关的数据的类。可以在activity或fragment重新创建时保存数据的完整性,避免因为生命周期的问题导致数据丢失。

优势:

  1. 保存数据的完整性。ViewModel 可以在屏幕旋转等配置更改时保存数据并重新创建 Activity 或 Fragment,从而保持数据的完整性,避免因为生命周期变化而导致的数据丢失
  2. 简化代码:使用 ViewModel 可以将 UI 相关的数据与 UI 控件分离,避免了在 Activity 或 Fragment 中处理数据逻辑的繁琐代码,使代码更加清晰、简洁。
  3. 支持数据共享:ViewModel不会随着Activity的屏幕旋转而销毁,减少了维护状态的代码成本(数据的存储和读取、序列化和反序列化)。
  4. 支持响应式编程:ViewModel 可以与 LiveData 或 RxJava 等响应式编程库一起使用,实现数据的实时更新和响应。

劣势:

  1. 不适合处理长时间运行的任务。viewmodel主要用于管理UI相关的数据
  2. 数据持久化需要额外处理。保存的数据只是暂时性的

ViewModel简单原理

获取方式,以以下两种方式为例

viewModel = ViewModelProvider.NewInstanceFactory().create(MyViewModel::class.java)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

ViewModelProvider

主要定义了如何获取ViewModel,通过两种工厂或者get方法

1.工厂

public interface Factory {
    @NonNull
    <T extends ViewModel> T create(@NonNull Class<T> modelClass);
}

NewInstanceFactory实现了Factory接口,AndroidViewModelFactory(构造函数需要传入Applciation,可以创建AndroidViewModel,应用上下文感知ViewModel )又继承NewInstanceFactory。它们实现了create方法,传入一个Class,并返回它的实例

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

2.get方法

ViewModelProvider构造函数中,需要一个ViewModelStoreOwner参数,同lifecycle,一般是activity和fragment。

public interface ViewModelStoreOwner {
    @NonNull
    ViewModelStore getViewModelStore();
}

最终都会调用这个构造函数来初始化。

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
    mFactory = factory;
    mViewModelStore = store;
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {

    //mViewModelStore通过key获取对应的viewmodel
    ViewModel viewModel = mViewModelStore.get(key);

    //如果传入的modelClass和获取到的viewModel相同,或者为它的子类等
    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            ((OnRequeryFactory) mFactory).onRequery(viewModel);
        }
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    //根据不同的参数创建viewModel,
    if (mFactory instanceof KeyedFactory) {
        viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
    } else {
        viewModel = mFactory.create(modelClass);
    }
    //每次创建完成,都添加进去
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

ViewModelStore

存储ViewModel类,通过Map存储

public class ViewModelStore {

    //key-value来保存ViewModel
    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
        return mMap.get(key);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

ViweModelProvider获取到ViewModelStore实例,是通过传入的activity或者fragment,在构造函数中调用了owner.getViewModelStore()(或者直接传入ViewModelStore和Factory)。因为activity或者fragment都实现了ViewModelStoreOwner接口,重写了getViewModelStore方法,获取到对应的ViewModelStore实例。

注意:ViewModel 的生命周期不同于 Activity 和 Fragment,它是被系统缓存的,因此可能会出现数据被清除的情况。在使用 ViewModel 时应该注意它的生命周期,及时保存数据并恢复数据。

四、DataBinding

在列表中乱用,因为DataBinding数据绑定是延迟一帧的,如果列表中的ItemView的宽高需要计算后才能正确展示,不建议使用DataBinding操作。否则会看到列表ItemView明显的撑开动画,体验不好。

此处可以使用dataBinding.executePendingBindings()快速渲染布局解决