Android架构灵魂组件Lifecycle的生命周期机制详解

news2024/11/16 17:35:34

在这里插入图片描述

前言:写作就跟生活一样,是一趟发现之旅。

前言

在早期 Andorid 架构中,生命周期的事件监听和状态查询,我们需要自定义一套提供侦测功能的 Activity/Fragment 基类及回调接口,在 Activity/Fragment 的生命周期方法中实现依赖组件的操作,在外部进行事件监听和状态查询。这种模式会导致代码条理性很差而且会扩散错误。

Lifecycle 引入后,可以避免在 Activity/Fragment 生命周期方法内写太多的业务逻辑处理代码,这样可以使我们的业务逻辑更加解耦。有助于您编写出更有条理且往往更精简的代码,此类代码更易于维护。

什么是Lifecycle

Lifecycle 是一个具备宿主生命周期感知能力的组件。它持有组件(Activity/Fragment)生命周期状态信息,并且允许其观察者监听宿主生命周期状态变化

一、Lifecycle的使用

build.gradle 文件中添加依赖:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-common:2.5.1"

使用 Lifecycle 观察宿主状态有三种实现方式。

1.继承LifecycleObserver

第一种是实现 LifecycleObserver 接口,采用注解方式,使用 @OnLifecycleEvent 标记自定义的方法以实现回调。

//1.自定义LifecycleObserver观察者,用注解声明每个方法观察宿主的状态
public class MyLifecycleObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart(@NotNull LifecycleOwner owner) {

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop(@NotNull LifecycleOwner owner) {

    }
}

//2.宿主中注册观察者,观察宿主生命周期状态变化
class MyFragment extends Fragment {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyLifecycleObserver observer = new MyLifecycleObserver();
        getLifecycle().addObserver(observer);
    }
}

实现 LifecycleObserver 接口,只需要在指定方法上面标记注解,来观察宿主的生命周期,注解里面标记着生命周期事件类型就可以了。然后在宿主注册这个 LifecycleObserver,它不需要销毁的时候进行反注册。

2.实现DefaultLifecycleObserver接口

第二种方式:定义一个类,实现 DefaultLifecycleObserver 接口,里面提供了完整的生命周期事件,为所有的生命周期事件都定义了对应的回调方法。它实现了 FullLifecycleObserver 接口,使用了 default 关键字空实现了各个方法。

class MyFullLifeObserver : DefaultLifecycleObserver {

    override fun onCreate(owner: LifecycleOwner) {}

    override fun onStart(owner: LifecycleOwner) {}

    override fun onResume(owner: LifecycleOwner) {}

    override fun onPause(owner: LifecycleOwner) {}

    override fun onStop(owner: LifecycleOwner) {}

    override fun onDestroy(owner: LifecycleOwner) {}
}

使用 DefaultLifecycleObserver 后,就需要把注解实现相关逻辑移除。即使保留注解,由于 Lifecycling 的处理逻辑(系统架构逻辑中所有传入的观察者都会经过 Lifecycling 处理,下面会讲解到),任何 FullLifecycleObserver 的实现类 (即包括DefaultLifecycleObserver) 内部所有的 @OnLifecycleEvent 注解都会失效。

3.实现LifecycleEventObserver

第三种方式:实现 LifecycleEventObserver,它是 LifecycleObserver 的子接口。只有一个 onStateChanged 方法,以 Lifecycle.Event 入参提供事件区分的形式,进行统一方法回调。

interface LifecycleEventObserver : LifecycleObserver {
    // 宿主生命周期变化的事件都会通知到这个方法
    fun onStateChanged(owner: LifecycleOwner?, event: Lifecycle.Event?)
}

//继承自LifecycleEventObserver,复写onStateChanged方法
class MyLifecycleEventObserver : LifecycleEventObserver {
    override fun onStateChanged(owner: LifecycleOwner?, event: Lifecycle.Event?) {
        //需要自行判断Event是onStart还是onStop
    }
}

无论哪一种方法都需要在宿主中注册观察者。推荐使用第二种和第三种方式,第一种不推荐使用。

二、Lifecycle 组件架构

为下面更好深入理解原理,我们先来简单了解下 Lifecycle 组件中几个重要的类:

  • Lifecycle(生命周期) :一个核心抽象类,用于存储有关组件(如 activity/fragment 的生命周期状态的信息,并允许其他对象观察此状态。继承该类的子类,表示本身是一个 具有Android生命周期特性 的对象。

  • LifecycleOwner核心接口,Lifecycle 持有者,该接口的实现类表示能够为外部提供Lifecycle实例。具有 Android 生命周期的类。这些事件可以被自定义组件用来处理生命周期的变化,而不需要在 Activity/Fragment 中实现任何代码。

  • LifecycleRegistry:核心类,Lifecycle 的实现类,可以处理多个观察者。实现 Lifecycle 定义生命周期观察订阅,生命周期查询的方法。还实现了架构中,生命周期变化时触发的自身状态处理和相关对观察者的订阅回调的逻辑。

  • LifecycleObserver:观察者,将一个类标记为生命周期观察者。实现该接口的类,通过注解的方式,可以通过被 LifecycleOwner 类的 addObserver() 方法注册,LifecycleObserver 便可以观察到 LifecycleOwner生命周期事件

  • State :当前生命周期所处的状态

  • Event :当前生命周期改变对应的事件。从框架和 Lifecycle 类分派的生命周期事件。这些事件对应到 activity/fragment 中的回调事件。

LifecyclerOwner、Lifecycle、LifecyleRegistry 和 Observer 的关系如下图:

Lifecycle架构图

一般来说宿主代表着 Activity/Fragment,都实现了 LifecyclerOwner 接口;那么每个宿主必须复写 getLifecycle(),并且返回一个 Lifecycle 对象,这个 Lifecycle 对象实际上是LifecycleRegistry,只不过它采用的是面向接口的编程方式,我们对 LifecycleRegistry 注册 Observer 的时候,可以是 LifecycleObserverFullLifecyclerOberverLifecyclerEventObserver

三、Lifecycle 原理剖析

系统框架中,LifecycleOwner 接口的实现类为 ComponentActivityFragment,两者提供的 Lifecycle 对象,是系统框架实现中 Lifecycle 的唯一子类 LifecycleRegistry

1.Fragment是如何实现Lifecycle的

public class Fragment implements LifecycleOwner {
    // 创建LifecycleRegistry 并且把this传递进去
    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        //2.复写自LifecycleOwner,所以必须new LifecycleRegistry对象返回
        return mLifecycleRegistry;
    }
    //······
}

Fragment 内 Lifecycle 核心代码片段,实现了 LifecycleOwner 接口,它表示生命周期宿主,持有生命周期(Lifecycle对象),该接口的生命周期的改变会被其注册的观察者 LifecycleObserver 观察到并触发其对应的事件。

必须复写 getLifecycle() 这个方法,返回的实际是 mLifecycleRegistry,说明 LifecycleLifecycleRegistry 的父类,这是一种面向接口的编程思想。

public class Fragment implements LifecycleOwner {
    //······
    void performCreate(Bundle savedInstanceState) {
        //······
        onCreate(savedInstanceState);
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

    void performStart() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    void performResume() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }

    void performPause() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
    }

    void performStop() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
    }

    void performDestroy() {
        mChildFragmentManager.dispatchDestroy();
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        //······
     }
}

我们注册 Lifecycle 的时候,实际上都注册到 LifecycleRegistry 里面去了。通过 handleLifecycleEvent() 分发自己的状态到每个观察者,从而实现观察生命周期实现变化的能力。看起来简单实际上 Lifecycle 在分发生命周期的时候并不简单,所有逻辑重点都在 LifecycleRegistry

Fragment 是如何派发生命周期的?也就是它会在自己生命周期里面,让 LifecycleRegistry 去分发生命周期事件,给每一个观察者。但是 Activity 中并不是这么做的。

2.Activity是如何是实现Lifecycle的

Activity 实现 Lifecycle 的核心源码,需要来到 ComponentActivity 里面,同样也是实现了 LifecycleOwner 接口:

public class ComponentActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    //复写getLifecycle(),返回LifecycleRegistry对象
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //往Activity上添加一个fragment,用以报告生命周期的变化
        //目的是为了兼顾不是继承自AppCompactActivity的场景
        ReportFragment.injectIfNeededIn(this);
    }
}

与上面 Fragment 的实现类似,它实现了 LifecycleOwner,表示一个生命周期的宿主,必须实现 getLifecycle() 方法,返回一个 Lifecycle,也就是 LifecycleRegistry

但是在 ComponentActivity 里面并没有在它的每个生命周期方法里面把它的状态分发给一个观察者,但是在 onCreate() 方法里面调用 ReportFragment.injectIfNeededIn(this) 这种做法实际上是往自己里面添加了一个不可见的 Fragment,专门用于报告分发给每个观察者。

public class ReportFragment extends Fragment {
    public static void injectIfNeededIn (Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // API 29 以上可以直接注册正确的生命周期回调
            activity.registerActivityLifecycleCallbacks(
                new LifecycleCallbacks ()
            );
        }
        // 兼容API 29之前的,需要支持直接继承Activity的,使用Fragment来正确获得生命周期事件
        android.app.FragmentManager manager = activity . getFragmentManager ();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment (), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
        }
    }
} 

所以 Activity 事件的分发是依靠 ReportFragment 来完成的。

  • API 29 以下: 主要是通过 ReportFragment 将自身添加到 Activity 中实现。
  • API 29 及以上:Activity 中增加一组 ActivityLifecycleCallbacks 的相关方法,可以直接通过注册 ActivityLifecycleCallbacks 观察生命周期。

ComponentActivity 为什么这么做而不直接在 Activity 内部直接分发呢?主要是为了兼顾不是继承自 AppCompatActivity 的场景。有可能是直接继承自 Activity,然后自己实现了 Lifecycle 接口。

public class ReportFragment extends Fragment {
    // 增加dispatch重载,尝试获取Activity中的LifecycleRegistry并调用 handleLifecycleEvent
    static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
    // 2.各个生命周期方法里面都调用了dispatch()方法
    @Override
    public void onStart() {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }
    //······

    // 3.拿到Activity的Lifecycle对象,把当前的事件分发给每个观察者
    private void dispatch(@NonNull Lifecycle.Event event) {
        if (Build.VERSION.SDK_INT < 29) {
            // 在API 29之前从ReportFragment分派事件。
            // 在API 29+上,由reportfragment.injectifneededdin中添加的activitylifecyecallbacks处理
            dispatch(getActivity(), event);
        }
    }
}

为了前向兼容,ReportFragment 依然会被添加到 Activity,并在 dispatch() 中增加过滤避免出现二次调用。

ReportFragment 会在侦测到 Activity 生命周期变化的时候调用 LifecycleRegistry.handleLifecycleEvent() 传入对应的状态。
这时候会有一个类 LifecycleDispatcher:

//挂钩到Activity的回调并进行观察
class LifecycleDispatcher {
    private static AtomicBoolean sInitialized = new AtomicBoolean(false);

    static void init(Context context) {
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            // 监听到每个Activity打开的事件
            ReportFragment.injectIfNeededIn(activity);
        }
    }
}

在它的 init() 方法里面调用了 registerActivityLifecycleCallbacks(),这里就能监察到每个 Activity 打开的事件,会再次利用 ReportFragment.injectIfNeededIn(activity),也就是说往每个 Activity 里面注册一个 ReportFragment,用于分发和报告当前宿主的生命周期到每个观察者,它这里是以一个切面编程的方式注入了一个 Fragment 对象,尽管我们是继承子 Activity,只要你实现了 LifecycleOwner 的接口,也能具备生命周期分发的能力。所以 Activity 生命周期分发的功能提取到 ReportFragment 里面,主要是为了不是继承自 AppCompatActivity 的场景。

到这里 Activity/Fragment 各自是如何实现 Lifecycle 能力的已经分析完成。但是无论如何生命周期能力都是依赖 LifecycleRegistry 来完成的。

3.LifecycleRegistry 源码分析

它是 Lifecycle 的实现,可以处理多个观察者。生命周期事件分发都是依靠 LifecycleRegistry 来完成的。先从添加观察者方法开始:

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("addObserver");
    // 1.初始化状态,当前宿主的状态
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    // 2.将observer封装成 ObserverWithState,是一个拥有宿主状态的观察者
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // 添加到Map集合中
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    // 3.计算出它应该到达的状态,也就是当前宿主的状态
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
    // 4.在while()循环中,会让当前的观察者的状态从init状态前进到当前宿主的状态
    //Observer的状态与targetState比较,如果小于0说明观察者的状态还没有到达targetState的状态
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        pushParentState(statefulObserver.mState);
        // 5.让Observer的状态前进到targetState
        final Event event = Event.upFrom(statefulObserver.mState);
        // 6. 分发事件
        statefulObserver.dispatchEvent(lifecycleOwner, event);
        popParentState();
        // 从新计算mState
        targetState = calculateTargetState(observer);
    }

    if (!isReentrance) {
        //同步状态
        sync();
    }
}

addObserver(observer) 里面,初始化状态,并且把observer封装成一个ObserverWithState,一个拥有宿主状态的观察者,然后添加到Map集合当中。

这里主要做了四件事:

  1. 初始化状态,将 observer 封装成 ObserverWithState,是一个拥有初始状态的观察者;
  2. 计算出它应该到达的状态,也就是当前宿主的状态;
  3. while 循环会让当前的观察者的状态从 INITIALIZED 状态前进到当前宿主的状态,Observer 的状态小于 targetState 说明观察者的状态还没有到达 targetState 的状态,那么就会让 Observer 的状态前进到 targetState;
  4. Observe 调用 dispatchEvent() 分发事件。

每个步骤都很重要,我们来一一分析:

4.状态与事件

State 是一个枚举,表示宿主的状态,但是宿主的状态和宿主的生命周期不是同一个概念。

public enum State {
    // 宿主的销毁状态,onDestory()之后
    DESTROYED,
    // 宿主的初始状态,onCreate()之前
    INITIALIZED,
    // 宿主的创建状态,onCreate()之后,onStop()之前
    CREATED,
    // 宿主的启动状态,onStart()之后,onPasue()之前
    STARTED,
    // 恢复状态,onResume()之后
    RESUMED;
}

比如宿主切换到后台,会执行 onPause() 方法,那么宿主的状态是什么状态?再从后台切回前台会执行 onStart() 再执行 onResum(),所以切换到后台的时候,执行了 onPause 这个事件,它的状态会变成 STARTED 的状态。可以看到它是没有 PAUSE 状态的。

这里还定义了 Event 事件,一个枚举,表示生命周期事件。它与宿主的生命周期一一对应。

public enum Event {
     //LifecycleOwner的onCreate事件的常量
    ON_CREATE,
     //LifecycleOwner的onStart事件的常量
    ON_START,
     //LifecycleOwner的onResume事件的常量
    ON_RESUME,
     //LifecycleOwner的onPause事件的常量
    ON_PAUSE,
     //LifecycleOwner的onStop事件的常量
    ON_STOP,
     //LifecycleOwner的onDestroy事件的常量
    ON_DESTROY,
     //可以匹配所有事件的常量
    ON_ANY
}

宿主生命周期与宿主状态关系图:

State与Event关系图

宿主在创建之初肯定是处于 INITIALIZED 状态,执行了 onCreate() 方法之后就会进入 CREATED 状态,接着执行了 onStart() 方法之后就会进入 STARTED 状态,执行了 onResume() 就会进入 RESUMED 状态,这是生命周期前进的过程,生命周期倒退过程同理。这里就是宿主的生命周期状态和事件完整的流程。

5.状态比较和升降级

回到 addObserver() 方法中:

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("addObserver");
    // 1.获取observer需要设置的初始状态
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    // 2.将observer封装成 ObserverWithState,并绑定初始的生命周期状态
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // 添加到Map集合中
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    // 3.计算出它应该到达的目标状态
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
    // 4.在while()循环中,会让当前的观察者的状态从init状态前进到目标状态
    //Observer的状态与targetState比较,如果小于0说明观察者的状态还没有到达targetState的状态
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        pushParentState(statefulObserver.mState);
        // 5.让Observer的状态升级到targetState
        final Event event = Event.upFrom(statefulObserver.mState);
        // 6. 分发事件,同步状态
        statefulObserver.dispatchEvent(lifecycleOwner, event);
        popParentState();
        // 重新计算mState
        targetState = calculateTargetState(observer);
    }

    if (!isReentrance) {
        //同步状态
        sync();
    }
}

在初始状态中,只要不是在 onDestory 注册的 Observer,每个观察者的初始状态都是 INITIALIZED 状态。在 while 循环中,会让当前的观察者的状态从 INITIALIZED 状态升级到目标状态,如果观察者的状态小于目标状态,就会通过 Event.upFrom() 方法让生命周期升级。

比如我们在 onResme() 方法中注册一个观察者,那么它会接收到哪几种状态呢?INITIALIZED、ONSTART、ONRESUME 它都会有,这个逻辑就在 while 循环里面,先通过 calculateTargetState(observer) 计算出它应该到达的目标状态,也就是当前宿主的状态,然后会拿 Observer 的状态比较,如果小于0说明观察者的状态还没有到达 targetState 的状态,那么就会让 Observer 的状态升级到 targetState。那么是如何进行升级的呢?

// 计算传入状态升级所对应的事件
public static Event upFrom(@NonNull State state) {
    switch (state) {
        case INITIALIZED:
            return ON_CREATE;
        case CREATED:
            return ON_START;
        case STARTED:
            return ON_RESUME;
        default:
            return null;
    }
}

离开当前的状态到达更高的状态,事件的状态从较低向上升级。在 INITIALIZED 状态中接收的是 on_Create 事件,然后来到 dispatchEvent() 方法里面:

static class ObserverWithState {
    // 当前状态
    State mState;
    // Observer封装
    LifecycleEventObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    //事件分发逻辑
    void dispatchEvent(LifecycleOwner owner, Event event) {
        //根据Event获取目标状态
        State newState = event.getTargetState();
        // 获取最小状态
        mState = min(mState, newState);
        // 状态改变回调
        mLifecycleObserver.onStateChanged(owner, event);
        // 更新当前状态
        mState = newState;
    }
}

会根据 Event 反推出目标状态,在 event.getTargetState() 里面,如果 Event 事件是 ON_CREATE 那么就会到达 State.CREATED 的状态,在调用 mLifecycleObserver.onStateChanged(owner, event) 之后,mState = newState状态就变成新的状态,前进了一步,从 INITIALIZED 状态变成了 CREATED 状态。

// 获取事件目标状态
public State getTargetState() {
    switch (this) {
        // 如果事件是 ON_CREATE或者ON_STOP,那么状态会到达State.CREATED
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
            break;
    }
}

它在分发事件的时候是根据观察者的状态推导出分发的事件,然后再根据分发的事件推导出观察者的状态,在这个方法执行完后,会再次回到While()循环中,再次进行观察者状态与目标状态比较,当前状态 mState 已经变成 CREATE,
如果 targetState 是 INITIALIZED,那么就实现了状态的升级。

但是如果 targetState 是 RESUME,while循环比较还是小于0的,则会再次调用 Event.upFrom(mState)dispatchEvent() 方法,将状态升级到 STATED,继续循环升级到 RESUME,依此类推,mState = newState状态就变成新的状态 RESUME。直到观察者的状态和宿主的状态达到一致,然后退出While()循环,如下图

  • 添加Observer时,完整的生命周期事件分发

ObserverWithState 被创建之初状态为 INITIALIZED,如果在宿主的 onResume() 生命周期注册一个 Observer,会把宿主的 onCreate,onStart,onResume 都分发给 Observer

image.png

直到 Observer 的状态和宿主的状态对齐为止,而不是直接从 INITIALIZED 状态直接分发一个 RESUME 直接到达 RESUME,目的因为我们可以在任何地方注册,并且可以接收到完整的接收事件,从而完成初始化,暂停,释放的工作。

这是添加观察者时的事件分发流程。

6.Lifecycle是如何分发宿主状态的

那么宿主的生命周期变化之后是如何分发给每一个观察者的?

根据上面 Activity/Fragment 源码分析,它会在每个生命周期方法里面执行handleLifecycleEvent(event)event.getTargetState()根据当前的事件推导出每个观察者目标的生命周期状态。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    enforceMainThreadIfNeeded("handleLifecycleEvent");
    moveToState(event.getTargetState());
}

private void moveToState(State next) {
    if (mState == next) {
        return;
    }
    mState = next;
    mHandlingEvent = true;
    // 同步新状态事件
    sync();
    mHandlingEvent = false;
}

moveToState(next) 里面主要是做一些条件的判断,真正的状态同步是在 sync() 方法里面:

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    //循环,直到isSynced()同步完成,所有观察者的状态都分发完,状态都与宿主的状态一致
    while (!isSynced()) {
        mNewEventOccurred = false;
        // 1.宿主的状态小于观察者状态,观察者状态进行降级
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            //状态降级
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        // 2. 宿主的状态大于观察者状态,观察者状态进行升级
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            // 状态升级
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

isSynced() 判断这个接口里面注册的 Observer 是否所有观察者的状态都分发完成,都已经同步到跟宿主一致的状态。如果不是则进入状态判断:

  1. 宿主的状态小于观察者状态,观察者状态进行降级;
  2. 宿主的状态大于观察者状态,观察者状态进行升级。

如果宿主的状态小于观察者状态,这种发生在生命周期倒退的阶段,比如前台切换到后台,执行 onPause() 方法,宿主进入 STARED 状态,观察者还处于 RESUME 状态,backwardPass() 是让所有的观察者都倒退,和宿主一样的状态,并且分发相应的事件给他们,

private void backwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
            mObserverMap.descendingIterator();
    // 循环遍历所有观察者
    while (descendingIterator.hasNext() && !mNewEventOccurred) {
        Map.Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
        ObserverWithState observer = entry.getValue();
        // 循环对比单个观察者的状态,直到单个观察者同步到目标状态,观察者状态大于宿主状态,则将观察者状态降级处理
        while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            // 根据observer.mState 的状态降级,获取对应的Event事件
            Event event = Event.downFrom(observer.mState);

            pushParentState(event.getTargetState());
            // 分发相应的事件Event
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
}

这里的核心逻辑就是遍历所有观察者,根据当前观察者的状态,计算出它应该分发哪一种事件,由于是生命周期的倒退,这里执行的是 Event.downFrom(observer.mState),也就是生命周期的降级:

// 计算传入状态降级所对应的事件
public static Event downFrom(@NonNull State state) {
    switch (state) {
        // 如果当前的状态是 CREATED,发生生命周期倒退就是执行了ON_DESTROY,返回ON_DESTROY事件
        case CREATED:
            return ON_DESTROY;
        case STARTED:
            return ON_STOP;
        case RESUMED:
            return ON_PAUSE;
        default:
            return null;
    }
}

如果观察者是 RESUME 状态,发生生命周期倒退,就会返回一个 ON_PAUSE 事件,如果是 STARTED 状态发生生命周期的倒退也就是返回 ON_STOP 事件。

然后根据返回的事件,调用 observer.dispatchEvent() 分发给它,根据上面的分析,还会当前的事件推导出目标的状态,然后赋值给 mState。

static class ObserverWithState {
    void dispatchEvent(LifecycleOwner owner, Event event) {
        //根据Event获取目标状态
        State newState = event.getTargetState();
        // 获取最小状态
        mState = min(mState, newState);
        // 状态改变回调
        mLifecycleObserver.onStateChanged(owner, event);
        // 更新当前状态
        mState = newState;
    }
}

backwardPass() 执行完之后,观察者的状态就会降级到和宿主一样的状态,直到集合里面的所有观察者的状态和宿主的一样为止。

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    //所有观察者的状态都分发完,状态都与宿主的状态一致
    while (!isSynced()) {
        // ······
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        // 2. 宿主的状态和Observe状态比较,宿主的状态大于观察者状态,观察者状态进行升级
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            // 状态升级
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

同理,进入 sync() 的第二个判断条件,把当前宿主的状态和每个观察者的状态进行比较,如果大于0,生命周期前进(比如后台切换到前台),从 STARTES 状态切换到 RESUME 状态, forwardPass(lifecycleOwner) 逻辑与 backwardPass() 相似,只不过这是状态前进的过程,会调用 Event.upForm(observer.mState),根据当前观察者的状态在生命周期前进的时候计算出它应该分发哪一个事件。

private void forwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
            mObserverMap.iteratorWithAdditions();
    // 循环遍历所有观察者
    while (ascendingIterator.hasNext() && !mNewEventOccurred) {
        Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
        ObserverWithState observer = entry.getValue();
        // 观察者状小于于宿主状态,则将观察者状态升级处理
        while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            pushParentState(observer.mState);
            // 根据mState状态升级,获取对应的分发事件Event
            final Event event = Event.upFrom(observer.mState);
            // 分发完后就和宿主达到一致的状态
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
}

observer.dispatchEvent() 分发完就会与宿主达到一致的状态,直到 Observer 集合当中所有观察者与宿主的状态保持一致,并且退出这个循环。

到这里,宿主的生命周期和宿主状态的关系,每个生命周期变化的时候,都会分发相应的事件,并且根据这个事件推导出宿主的状态,遍历所有的观察者,让他们的状态也随之升级,或者降级,并且把本次事件分发给观察者。

7.如何区分LifecycleObserver的类型

那么这个事件它在分发的时候,是如何区分的 LifecycleObserver 还是 FullLifecycleObserver,亦或者是 LifecycleEventObserver 这三种类类型的?在 addObserver() 里面,每次注册一个 Observer 都会把它包装成一个 ObserverWithState

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;
    //把传递进来的observer转换成LifecycleEventObserver
    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        // 分发事件
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

它把传递进来的 observer 转换成 LifecycleEventObserver,分发事件的时候调用了 mLifecycleObserver.onStateChanged() 方法,但是我们在使用的时候明明是 LifecycleObserver 或者 FullLifecycleObserver,主要是原理在 Lifecycling.lifecycleEventObserver(observer) 里面,本质上是一个工具类,把传递进来的 observer 转化成 LifecycleEventObserver,主要是通过适配器来转化的。

static LifecycleEventObserver lifecycleEventObserver(Object object) {
    // 是否为LifecycleEventObserver类型
    boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
    // 是否为FullLifecycleObserver类型
    boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
    // 1.这种情况发生在自定义Observer,上面两种都实现了
    if (isLifecycleEventObserver && isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                (LifecycleEventObserver) object);
    }
    // 2. FullLifecycleObserver 将object当做FullLifecycleObserver传递
    if (isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
    }
    // 3. LifecycleEventObserver 直接返回object本身
    if (isLifecycleEventObserver) {
        return (LifecycleEventObserver) object;
    }
    //······
}
  1. 判断 observer 是否为 LifecycleEventObserver && FullLifecycleObserver,如果条件都成立(一般发生在自定义的 Observer,即实现了两个接口),返回了一个FullLifecycleObserverAdapter,它实现了 LifecycleEventObserver 接口,复写了onStateChanged()方法,判断 Event 的类型,从而回调传递进来的 FullLifecycleObserver 相应的方法,如果还实现了 mLifecycleEventObserver 接口,则最后还会回调mLifecycleEventObserver.onStateChanged()方法。
// 实现LifecycleEventObserver接口
class FullLifecycleObserverAdapter implements LifecycleEventObserver {
    // mFullLifecycleObserver回调生命周期方法
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        switch (event) {
            case ON_CREATE:
                mFullLifecycleObserver.onCreate(source);
                break;
            case ON_START:
                mFullLifecycleObserver.onStart(source);
                break;
            case ON_RESUME:
                mFullLifecycleObserver.onResume(source);
                break;
            case ON_PAUSE:
                mFullLifecycleObserver.onPause(source);
                break;
            case ON_STOP:
                mFullLifecycleObserver.onStop(source);
                break;
            case ON_DESTROY:
                mFullLifecycleObserver.onDestroy(source);
                break;
        }
        // 回调mLifecycleEventObserver的onStateChanged()方法
        if (mLifecycleEventObserver != null) {
            mLifecycleEventObserver.onStateChanged(source, event);
        }
    }
}
  1. 如果仅仅是实现了 FullLifecycleObserver,同样是返回了一个FullLifecycleObserverAdapter,但是 lifecycleEventObserver 为 null,说明不再回调 onStateChanged(source, event) 方法,实际上通过 FullLifecycleObserverAdapter 包装实现转化过程,将 LifecycleObserver 转化为 LifecycleEventObserver

  2. 如果是直接实现了 LifecycleEventObserver 的则直接返回,那么在生命周期事件分发的时候, Observer 就能直接分发到 onStateChanged() 这个方法里面。

static LifecycleEventObserver lifecycleEventObserver(Object object) {
    ·····
    final Class<?> klass = object.getClass();
    // 获取Observer构造器类型,是否添加了注解编译器
    int type = getObserverConstructorType(klass);
    // 提供了两种策略
    if (type == GENERATED_CALLBACK) {
        //提供了两种策略
        List<Constructor<? extends GeneratedAdapter>> constructors =
                sClassToAdapters.get(klass);
        if (constructors.size() == 1) {
            GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                    constructors.get(0), object);
            return new SingleGeneratedAdapterObserver(generatedAdapter);
        }
        GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
        for (int i = 0; i < constructors.size(); i++) {
            adapters[i] = createGeneratedAdapter(constructors.get(i), object);
        }
        // 返回CompositeGeneratedAdaptersObserver
        return new CompositeGeneratedAdaptersObserver(adapters);
    }
    // 返回ReflectiveGenericLifecycleObserver,内部实现依赖反射
    return new ReflectiveGenericLifecycleObserver(object);
}

上面的代码则是判断 LifecycleOberver,我们知道它只是一个空实现,但是为什么还要定义这个接口呢?这里仅仅是起到一个约束和规范的作用,方便在运行的时候判断 Observer 是那种类型。

public interface LifecycleObserver {

}

如果 Observer 是实现了 LifecycleOberver 这个接口的,它在运行的时候,分发事件的时候它提供了两种策略:

  1. 第一种是把 Observer 包装成一个 ReflectiveGenericLifecycleObserver,同样是实现了LifecycleEventObserver,在 onStateChanged() 调用了 invokeCallbacks() 方法通过反射的形式来调用自定义的 Observer 中相关方法。
// LifecycleObserver内部实现依赖反射
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
        //通过反射的形式来调用自定义的Observer中相关方法
        mInfo.invokeCallbacks(source, event, mWrapped);
    }
}
  1. 第二种如果在 gradle 文件中添加了 lifecycle_compiler 依赖,它实际上是编译器的意思,里面包含了一个注解处理器,在编译阶段就会为 Observers 生成相应适配的类。

image.png

比如上面 Lifecycle 实现方式的第一种:

public class MyLifecycleObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart(@NotNull LifecycleOwner owner) {

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop(@NotNull LifecycleOwner owner) {

    }
}

编译时会在 build.generated.source.kapt.debug 文件下自动生成MyLifecycleObserver_LifecycleAdapter.java 文件,在它的实现里面,就是根据事件的类型,回调到 MyLifecycleObserveronStart()onStop() 方法,这里为什么能直接回调呢?因为它在编译阶段生成的这个类,就能扫描到 MyLifecycleObserver 中的方法上标记的注解OnLifecycleEvent,然后拿到方法的名称,以及它的参数,生成下面的源码,就不用使用反射调用 MyLifecycleObserver 类中的方法了。

image.png

但是如何判断有没有引入 lifecycle-compiler 这个编译器的,通过 int type = getObserverConstructorType(klass) 判断构造器类型,跟踪来到 generatedConstructor() 中:

// 传入一个Class,实际上是就是上面定义的MyLifecycleObserver
private static Constructor<? extends GeneratedAdapter> generatedConstructor(Class<?> klass) {
    try {
        //获取包名
        Package aPackage = klass.getPackage();
        //获取类名
        String name = klass.getCanonicalName();
        final String fullPackage = aPackage != null ? aPackage.getName() : "";
        // 获取adapterName拼接后的类名
        final String adapterName = getAdapterName(fullPackage.isEmpty() ? name :
                name.substring(fullPackage.length() + 1));

        final Class<? extends GeneratedAdapter> aClass =
                (Class<? extends GeneratedAdapter>) Class.forName(
                        fullPackage.isEmpty() ? adapterName : fullPackage + "." + adapterName);
        Constructor<? extends GeneratedAdapter> constructor =
                aClass.getDeclaredConstructor(klass);//反射加载这个类,
        if (!constructor.isAccessible()) {//如果没有异常,说明类存在
            constructor.setAccessible(true);
        }
        return constructor;
    } catch (ClassNotFoundException e) {
        return null;
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    }
}

adapterName 的类名拼接,实际上是 MyLifecycleObserver 拼接上 _LifecycleAdapter,如下:

public static String getAdapterName(String className) {
    return className.replace(".", "_") + "_LifecycleAdapter";
}

如果类存在了,说明引入了 lifecycle-compiler 这个编译器,如果抛出异常就说明没有引入这个编译器。

这样它就能够区分,对于是直接实现 LifecycleObserver 的情况,是返回 CompositeGeneratedAdaptersObserver 还是返回 ReflectiveGenericLifecycleObserver,从而采用不同的策略来回调方法。

四、总结

Lifecycle 原理时序图如下:

在这里插入图片描述

  1. 监听过程就是 Activity/Fragment 继承 LifecycleOwner,并在子类 CommponentActivity 中创建 Lifecycle 的子类 LifecycleRegistry。复写 getLifecycle() 的方法中将子类 LifecycleRegistry 返回
  2. 在 onCreate() 中注入 ReportFragment,在生命周期回调后,通过 getLifecycle() 的方法得到 LifecycleRegistry 对象中的 handleLifecycleEvent(event) 方法给每个观察者派发生命周期事件
  3. addObserver() 中先初始化状态,然后计算出它应该到达的状态(目标状态),while()循环会让当前的观察者的状态从init状态前进到目标状态,再根据状态获取相应的事件,Observe 调用 dispatchEvent() 分发事件
  4. 宿主每个生命周期方法里面执行 handleLifecycleEvent(event),event.getTargetState() 根据当前的事件推导出每个观察者目标的生命周期状态,进行升级或者降级处理。然后遍历所有观察者,根据当前观察者的状态,计算出它对应的事件,分别进行 observer.dispatchEvent() 分发事件。

关于 Lifecycle 面试常问几个问题:

  1. Activity 里面是如何实现 Lifecycle 事件的分发的?

答:是通过添加透明 ReportFragment.

  1. 在 onResume 方法里面注册 Observer,是否能接受到完整的分发事件?

答:能。

Lifecycle 几乎是 Jetpack 组件的核心,所有具有生命周期感知能力的组件都会用到 Lifecycle,包括 ViewModel和 Livedata。Lifecycle 实现了执行的逻辑和活动的分离,代码解耦并且增加了代码的额可读性。Lifecycle 在活动结束时自动移除监听,避免了生命周期的问题。

总的来说,观察宿主生命周期有三种写法,推荐第二种和第三种,第一种需要使用注解标记,要么是反射,要么是要添加注解处理器,生成适配的类。

这是一个Jetpack组件 + MVVM架构模式的开源实战项目,加入 组件化模块化协程Flow短视频打造一个大型的 Android 项目架构。项目地址:https://github.com/suming77/SumTea_Android

点关注,不迷路


好了各位,以上就是这篇文章的全部内容了,很感谢您阅读这篇文章。我是suming,感谢各位的支持和认可,您的点赞就是我创作的最大动力。山水有相逢,我们下篇文章见!

本人水平有限,文章难免会有错误,请批评指正,不胜感激 !

参考链接:

  • Lifecycle官网

希望我们能成为朋友,在 Github博客 上一起分享知识,一起共勉!Keep Moving!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/637251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

618必买清单,几款实用的数码好物分享

只剩一周的618&#xff0c;各大电商平台都在为我们献上一场豪华盛宴&#xff01;小伙伴们&#xff0c;你们的购物车已经快满了吗&#xff1f;楼主翻了翻自己的账单&#xff0c;发现很多商品的活动力度都非常给力&#xff0c;简直就是给我们的钱包来了一次“减负”操作。今天&am…

记录基于Vue.js的移动端Tree树形组件

目录 一、Liquor Tree 入门 &#xff1a; Development Component Options 组件选项 Structure 结构 二、vue-treeselect Introduction 介绍 Getting Started 入门 Vue 树形选择器&#xff08; Vue tree select &#xff09;组件在搭建 Vue 的 app 中特别常用&#xff0…

算法提高-图论- 负环

负环 负环AcWing 904. 虫洞AcWing 361. 观光奶牛AcWing 1165. 单词环 负环 本博客主要介绍spfa求负环 一般用第二种方法 第一种方法如果每个点入队n次&#xff0c;每次入队也要遍历n次&#xff0c;那么时间复杂度就是n2 第二种方法时间复杂度是n&#xff0c;只要发现最短路边数…

城市道路路面病害检测识别分析,以RDD赛事捷克-印度-日本集成融合数据集为例,基于yolov5m模型开发构建城市道路病害检测识别系统

城市道路病害检测是最近比较热门的一个任务领域&#xff0c;核心就是迁移深度学习目前已有的研究成果来实现实时城市道路路面病害的检测识别分析&#xff0c;在我之前的很多博文中都有做过类似桥梁、大坝、基建、隧道等水泥设施裂缝裂痕等目标检测相关的项目&#xff0c;除此之…

SQL Server 2008 定时自动备份和自动删除方法

SQL Server 2008 数据定时自动备份和自动删除方法&#xff0c;同一个计划兼备数据备份数数据删除的操作方法 工具/原料 SQL Server 2008 方法/步骤 1、 点击实例名下的【管理】-【维护计划】-点击鼠标右键&#xff0c;点击【维护计划向导】&#xff0c;填写计划名称&…

崛起的中国卫浴:市场与创新双驱动

5月28日&#xff0c;国产大飞机C919完美完成了商业航班首飞。从中国制造到中国创造&#xff0c;C919的成功是无数中国企业、中国品牌的缩影。 改革开放至今的短短四十年间&#xff0c;中国经历了“以市场换技术-模仿式创新-源创新”三个阶段&#xff0c;上世纪90年代&#xff…

【IMX6ULL驱动开发学习】07.注册驱动设备_分配固定的次设备号_cdev

一、register_chrdev 在之前的hello驱动中&#xff0c;注册驱动设备的方式如下 /*初始化设备方法1&#xff1a;自动分配设备号&#xff0c;占用所有次设备号*/ major register_chrdev(0,"hello_drv",&hello_fops);使用 register_chrdev 分配设备号的方式比较…

【JAVA开发环境配置】 我也可以让JDK版本来去自由的切换了! 哈哈哈哈 舒服!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

单页面控制中心 vue-router

一、 路由的基本配置 1. 在router->index.js中&#xff0c;配置一个懒路由&#xff0c;定义页面加载哪个组件 import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const routes []// 配置一个懒路由,不然会加载页面下所有组件 const router new Vu…

基于微信小程序的失物招领系统设计与实现

博主介绍&#xff1a;✌擅长Java、微信小程序、Python、Android等&#xff0c;专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案…

BI工具+方案:火速构建电商数据分析架构

电商数据分析该怎么做&#xff1f;谁都知道电商数据分析讲究效率和精细化&#xff0c;光是围绕电商销售分析&#xff0c;就需要制作包括管理驾驶舱、销售预算分析、店铺销售增长趋势、店铺排名分析、商品退货分析等近20种电商数据分析报表。怎么才能又快又好地完成智能数据分析…

java设计模式之:装饰器模式

前言 在软件设计中&#xff0c;我们也有一种类似新房装修的技术可以对已有对象&#xff08;新房&#xff09;的功能进行扩展&#xff08;装修&#xff09;&#xff0c;以获得更加符合用户需求的对象&#xff0c;使得对象具有更加强大的功能。这种技术对应于一种被称之为装饰模…

Bug序列——容器内给/root目录777权限后无法使用ssh免密登录

Linux——创建容器并将本地调试完全的前后端分离项目打包上传docker运行_北岭山脚鼠鼠的博客-CSDN博客 接着上一篇文章结尾出现403错误时通过赋予/root目录以777权限解决403错误。 chmod 777 /root 现在又出现新的问题&#xff0c;远程ssh无法免密登录了&#xff0c;即使通过…

准备了2个月,怒刷面试题,4面字节跳动,顺利拿到 offer

说到字节跳动的经历还是比较搞笑的。一开始我特别想去那个游戏测试部门&#xff0c;当然 data测试部门也是特别想去的&#xff0c;但是提前批只能投一个&#xff0c;于是投了游戏&#xff0c;结果第二天就给我挂了。。。中间北京的捞我&#xff0c;但是不想去北京所以拒绝了&am…

说透缓存击穿、穿透、雪崩及常用解决方案

文章目录 缓存击穿、穿透、雪崩及解决方案击穿、穿透、雪崩的意思缓存击穿缓存穿透缓存雪崩总结 系列文章目录 本文是系列文章&#xff0c;为了增强您的阅读体验&#xff0c;已将系列文章目录放入文章末尾。&#x1f44d;&#x1f44d;&#x1f44d; 缓存击穿、穿透、雪崩及解决…

我的内网渗透-metasploit基础

目录 MSF postgresql msf模块 永恒之蓝 木马下放 后渗透一些简单命令 MSF Msfconsole是Metasploit框架的主要控制台界面。 开源的渗透软件 postgresql 使用的是postgresql数据库&#xff08;metasploit所依载的数据库&#xff0c;没有他也可以运行metasploit框架&…

Vue中如何进行二维码生成与扫描?

Vue中如何进行二维码生成与扫描&#xff1f; 二维码是一种广泛应用于各种场合的编码方式&#xff0c;它可以将信息编码成一张二维图案&#xff0c;方便快捷地传递信息。在Vue.js中&#xff0c;我们可以使用一些库和组件来实现二维码的生成和扫描。本文将介绍如何在Vue中实现二…

高频RFID工业读写器在自动化产线上如何应用?

工业读写器在自动化生产上具有十分重要的作用&#xff0c;它可以对工业生产中的贴上RFID标签的各种零部件和产品&#xff0c;进行跟踪与识别。利用RFID技术进行非接触的物体识别和追踪&#xff0c;更好的掌握产线上的物料信息。 高频RFID工业读写器在自动化产线上如何应用&…

Android studio C++调试问题汇总

问题1&#xff1a;如下图所示&#xff0c;cpp目录不显示或cpp目录不显示C源文件。 此问题由由于abiFilter指定为armeabi&#xff0c;但armeabi架构已经不再支持的原因导致&#xff0c;将armeabi修改为armeabi-v7a或arm64等其他支持的架构即可&#xff0c;修改后如下图所示&…

致敬易语言,Excel衍生新型中文编程,Python用户:转折点到了

没有逃过被命运的捉弄 易语言作为中文编程里的老大&#xff0c;刚开始的时候&#xff0c;叫E语言。 创始人吴涛&#xff0c;地道的中国人&#xff0c;就是为了让中国人不再孜孜不倦的去追难懂的编程语言&#xff0c;降低开发门槛。 易语言的结局最终也没逃过被命运的捉弄&…