Jetpact-activity组件完全解析
前言
Jetpack-activity/fragment 是jetpack架构组件中最基础的部分。
底层对jetpack-lifecycle组件做了支持、为开发者能够直接使用jetpack架构组件提供了支持,因此要想彻底了解jetpack系列,先学习activity/fragment组件很有必要。
注意:
本文中源代码均使用 1.1.0稳定版本
引用
def activity_version = "1.1.0"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
继承结构:
源码解析
/**
* Base class for activities that enables composition of higher level components.
* <p>
* Rather than all functionality being built directly into this class, only the minimal set of
* lower level building blocks are included. Higher level components can then be used as needed
* without enforcing a deep Activity class hierarchy or strong coupling between components.
*/
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
//....
}
从 ComponentActivity
类的注释上可以得出两条信息:
ComponentActivity
是一个支持组合高级组件的基类Activity- 并没有将所有的组件都构建到这个类中,只是包含最基础的底层组件。开发者可以根据需要使用更高级别的组件,无需在组件之间强耦合。
构造器
ComponentActivity
在构造器中针对Android不同版本进行了简单兼容处理
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
//noinspection ConstantConditions
//如果在使用 Lifecycle 对象的时候还没有初始化则直接抛错,对于重写 getLifecycle() 方法需要注意
if (lifecycle == null) {
throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
+ "constructor. Please make sure you are lazily constructing your Lifecycle "
+ "in the first call to getLifecycle() rather than relying on field "
+ "initialization.");
}
//针对API 19以上兼容
if (Build.VERSION.SDK_INT >= 19) {
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_STOP) {
Window window = getWindow();
final View decor = window != null ? window.peekDecorView() : null;
if (decor != null) {
decor.cancelPendingInputEvents();
}
}
}
});
}
//Activity销毁时清除ViewMode中数据
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
//针对 19~23 版本 解决 InputMethodManager中 mNextServedView 内存泄漏问题
if (19 <= SDK_INT && SDK_INT <= 23) {
getLifecycle().addObserver(new ImmLeaksCleaner(this));
}
}
从构造器中代码来看做的事情比较多,但都是兼容性处理,有三个方面的处理:
- 针对API19以上兼容Activity停止时取消View还未执行的事件
- 针对API19以上Activity销毁时清除ViewMode中数据
- 针对API19~23版本Activity销毁时解决InputMethodManager中 mNextServedView持有Activity导致内存泄漏问题
Activity停止时取消View还未执行的事件
在 Activity
处于stop 时用户是看不到界面的,也没有必要再处理 View
的点击、长按、动画等事件。所以有必要将这些事件移除掉。
我们跟随源码看一下具体是怎么做的:
View层处理
上述代码会调用View
中 cancelPendingInputEvents()
这是个取消事件的总调度方法,它没有具体做事情,而是调用了 dispatchCancelPendingInputEvents()
来完成工作
public final void cancelPendingInputEvents() {
dispatchCancelPendingInputEvents();
}
void dispatchCancelPendingInputEvents() {
//位操作设置标志位
mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
//执行清除事件工作
onCancelPendingInputEvents();
//检查标志位是否正确 以确保完成了清除工作
if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
throw new SuperNotCalledException("View " + getClass().getSimpleName() +
" did not call through to super.onCancelPendingInputEvents()");
}
}
在 dispatchCancelPendingInputEvents()
方法中调用了 onCancelPendingInputEvents()
来完成具体的清除工作:
onCancelPendingInputEvents()
会清除已发送到消息队列的事件,延迟事件等 如果是自定义View
是可以重写此方法,来自定义指定那些事件是需要清除或保留的,但是需要注意要 super.onCancelPendingInputEvents()
要调用父类方法 完成 mPrivateFlags3变量的位操作
public void onCancelPendingInputEvents() {
//移除点击事件回调
removePerformClickCallback();
//取消等待的长按事件
cancelLongPress();
//对标识变量进行操作 在 dispatchCancelPendingInputEvents()对此变量有检查操作
mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
}
移除点击事件回调
在 removePerformClickCallback()
中直接调用 removeCallbacks
将 mPerformClick
点击事件传入
@UnsupportedAppUsage
private void removePerformClickCallback() {
if (mPerformClick != null) {
removeCallbacks(mPerformClick);
}
}
removeCallbacks(Runnable action)
才是真正移除事件处理的方法,凡是以下几种方式添加的事件或延迟事件都会移除
post()
postDelayed()
postOnAnimation()
postOnAnimationDelayed()
public boolean removeCallbacks(Runnable action) {
if (action != null) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
//移除指定回调
attachInfo.mHandler.removeCallbacks(action);
//移除Choreographer中动画回调
attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
Choreographer.CALLBACK_ANIMATION, action, null);
}
//移除等待队列中事件
getRunQueue().removeCallbacks(action);
}
return true;
}
移除长按事件
在 cancelLongPress()
中会分别调用 removeLongPressCallback()
清除长按回调 和 removeTapCallback()
移除长按产生的超时事件
removeLongPressCallback()
和 removeTapCallback()
都会调用 removeCallbacks(Runnable action)
来移除指定的事件,前面我们已经分析过了,就不再赘述了。
public void cancelLongPress() {
//移除长按回调事件
removeLongPressCallback();
//移除长按超时回调事件
removeTapCallback();
}
//移除长按回调
private void removeLongPressCallback() {
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}
}
//移除长按超时事件、修改标志位
private void removeTapCallback() {
if (mPendingCheckForTap != null) {
mPrivateFlags &= ~PFLAG_PREPRESSED;
removeCallbacks(mPendingCheckForTap);
}
}
Activity销毁时清除ViewMode中数据
Activity
销毁时清除ViewMode
中数据,需要依赖另一个组件-Lifecycle
支持。不仅是 ViewModel
在Jetpack 架构组件中很多组件都需要依赖 Lifecycle
组件。
我们重新看一下以下代码
//Activity销毁时清除ViewMode中数据
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
我们看到 !isChangingConfigurations()
为 true ,也就是Activity
配置没有修改情况下,在Activity
销毁时会调用 getViewModelStore().clear()
这里我们先将ViewModel
放一放,来看一下为什么在清除 ViewModel
中数据