当前位置:   article > 正文

Jetpact-activity组件完全解析_lifecycleonbackpressedcancellable什么意思

lifecycleonbackpressedcancellable什么意思

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"
  • 1
  • 2
  • 3
  • 4
  • 5

继承结构:

在这里插入图片描述

源码解析

/**
 * 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 {
   
        //....
}        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

ComponentActivity 类的注释上可以得出两条信息:

  1. ComponentActivity 是一个支持组合高级组件的基类Activity
  2. 并没有将所有的组件都构建到这个类中,只是包含最基础的底层组件。开发者可以根据需要使用更高级别的组件,无需在组件之间强耦合。

构造器

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));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

从构造器中代码来看做的事情比较多,但都是兼容性处理,有三个方面的处理:

  • 针对API19以上兼容Activity停止时取消View还未执行的事件
  • 针对API19以上Activity销毁时清除ViewMode中数据
  • 针对API19~23版本Activity销毁时解决InputMethodManager中 mNextServedView持有Activity导致内存泄漏问题
Activity停止时取消View还未执行的事件

Activity 处于stop 时用户是看不到界面的,也没有必要再处理 View的点击、长按、动画等事件。所以有必要将这些事件移除掉。

我们跟随源码看一下具体是怎么做的:

View层处理

上述代码会调用ViewcancelPendingInputEvents() 这是个取消事件的总调度方法,它没有具体做事情,而是调用了 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()");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

dispatchCancelPendingInputEvents() 方法中调用了 onCancelPendingInputEvents() 来完成具体的清除工作:

onCancelPendingInputEvents() 会清除已发送到消息队列的事件,延迟事件等 如果是自定义View 是可以重写此方法,来自定义指定那些事件是需要清除或保留的,但是需要注意要 super.onCancelPendingInputEvents() 要调用父类方法 完成 mPrivateFlags3变量的位操作

public void onCancelPendingInputEvents() {
   
    //移除点击事件回调
    removePerformClickCallback();
    //取消等待的长按事件
    cancelLongPress();
    //对标识变量进行操作 在 dispatchCancelPendingInputEvents()对此变量有检查操作
    mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
移除点击事件回调

removePerformClickCallback() 中直接调用 removeCallbacksmPerformClick点击事件传入

 @UnsupportedAppUsage
 private void removePerformClickCallback() {
   
     if (mPerformClick != null) {
   
         removeCallbacks(mPerformClick);
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

removeCallbacks(Runnable action)才是真正移除事件处理的方法,凡是以下几种方式添加的事件或延迟事件都会移除

  1. post()
  2. postDelayed()
  3. postOnAnimation()
  4. 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
移除长按事件

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
Activity销毁时清除ViewMode中数据

Activity销毁时清除ViewMode中数据,需要依赖另一个组件-Lifecycle支持。不仅是 ViewModel 在Jetpack 架构组件中很多组件都需要依赖 Lifecycle组件。

我们重新看一下以下代码

//Activity销毁时清除ViewMode中数据
getLifecycle().addObserver(new LifecycleEventObserver() {
   
    @Override
    
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/254043
推荐阅读
相关标签
  

闽ICP备14008679号