Jetpack-Lifecycle

Lifecycle介绍

相关类和接口

使用

实现原理

Lifecycle-生命周期感知组件

LifecycleJetpack中提供的一个用于感知生命周期的组件,在应用中主要用于监听 ActivityFragment的生命周期变化,在合适的时候释放资源,防止内存泄露。使用Lifecycle可以将依赖组件的代码从生命周期方法移入组件本身中。避免了直接在ActivityFragment的生命周期方法中操作组件。比如,我们常用的方式如下:

class MyActivity:AppCompatActivity() {
    override fun onStart() {
        super.onStart()
        LocationUtils.start()
    }

    override fun onStop() {
        super.onStop()
        LocationUtils.stop()
    }
}

如果多个页面都用到了这个工具类,就需要写多遍,如果多人开发,并不能保证一定都会调用对应的方法。这样难以维护。

androidx.lifecycle软件包提供了可用于构建生命周期感知组件的类和接口,这些组件可以根据ActivityFragment的当前生命周期状态自动调整其行为。

相关类和接口

Lifecycle

Lifecycle本身是一个抽象类,用于存储有关组件(如 ActivityFragment)的生命周期状态的信息,并允许其他对象观察此状态。它主要通过两个枚举类:Event和State来关联组件的生命周期。

LifecycleOwner

LifecycleOwner是一个接口,用于返回一个Lifecycle对象,表示生命周期拥有者,提供者,属于被观察的对象。

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

LifecycleObserver

LifecycleObserver是一个标记接口,任何类都可以通过实现该接口来感知组件生命周期的变化,属于观察对象。

public interface LifecycleObserver {
}

实现LifecycleObserver的组件可与实现LifecycleOwner的组件无缝协同工作,因为生命周期所有者可以提供生命周期,而观察者可以注册以观察生命周期。

应用

Activity和Fragment

在应用中,我们常用的就是监听ActivityFragment的生命周期。Support Library 26.1.0及更高版本或AndroidX中FragmentActivity已实现了LifecycleOwner接口。我们只需要将我们的工具类实现接口LifecycleObserver来检测或者感知ActivityFragment的生命周期即可。

  • 1.通过向对应的方法添加注解来监控组件的生命周期状态。
  • 2.通过调用LifecycleaddObserver()方法来添加观察者
class LocationUtils(lifecycle: Lifecycle) : LifecycleObserver {

    init {
        //添加观察者
        lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start() {
        TODO()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop() {
        TODO()
    }
}

//使用,创建对象后,在需要使用的地方直接调用对应的功能即可,不需要再外面关联组件的生命周期。
val location = LocationUtils(lifecycle)

如果我们需要从另一个ActivityFragment使用LocationUtils,只需对其进行初始化。所有设置和拆解操作都由类本身管理。 这样还有一个好处就是:如果start()改成在onResume()中调用,不需要更改调用的地方,只需要更改定义的地方。这样维护成本低。

自定义 LifecycleOwner

如果想把我们自定义的类变成为LifecycleOwner,就需要借助LifecycleRegistry将事件转发到该类,如下代码所示:

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}

使用生命周期感知组件可以很方便地管理生命周期:

  • 在粗粒度和细粒度位置更新之间切换。
  • 停止和开始视频缓冲。
  • 开始和停止网络连接。
    暂停和恢复动画。

如果Lifecycle的实现是AppCompatActivityFragment,那么当调用它们的onSaveInstanceState()方法时,Lifecycle的状态会更改为CREATED并且会分派ON_STOP事件。

实现原理

简单来说:就是通过一个无页面的Fragment。通过在对指定Activity注册无页面的Fragment,传递页面Activity生命周期Fragment。然后通过Fragment绑定LifecycleRegistry,当Fragment的生命周期变化时,回调LifecycleRegistryLifecycleObserver对象相应的生命周期回调方法。

我们观察Activity的生命周期,只要是通过下述代码:

 lifecycle.addObserver(this)

就以此为入口,看一下它的实现:getLifecycle()方法返回的是ComponentActivity中的mLifecycleRegistry,如果你用的是support包,它定义SupportActivity中,我这里使用的AndroidX

public class ComponentActivity extends androidx.core.app.ComponentActivity implements ...{
    ...
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    ...
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
    ...
}

我们调用的addObserver()方法,实际上调用的就是LifecycleRegistry里面的:

 public class LifecycleRegistry extends Lifecycle {
    ...
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //将传进来的observer包装成一个ObserverWithState,并放入集合中
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        ...
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            //分发事件
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            targetState = calculateTargetState(observer);
        }
    ...
    }
    ...
}

从上面可以看出有一个while循环,条件是比较观察者被观察者State的序数, DESTROYED、INITIALIZED、CREATED、STARTED和RESUMED的序数依次为0,1,2,3,4。状态变化后,在该循环体中,调用了statefulObserver.dispatchEvent()方法,分发事件。该方法的具体实现如下:

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

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

ObserverWithState创建的时候将传入的observer解析并返回接口LifecycleEventObserver实现类的对象,最后调用它的onStateChanged()方法。我们在使用Lifecycle的时候使用的是注解的方式:@onLifecycleEvent,那么注解处理器会将该注解解析并动态生成GeneratedAdapte代码,这个GeneratedAdapter会把对应的Lifecycle.Event封装为方法调用。最终通过GenericLifecycleObserveonStateChanged方法调用生成的GeneratedAdaptercallMechods()方法进行事件分发。

public class LocationUtils_LifecycleAdapter implements GeneratedAdapter {
    final LocationUtils mReceiver;

    LocationUtils_LifecycleAdapter(LocationUtils receiver) {
        this.mReceiver = receiver;
    }

    @Override
    public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,MethodCallsLogger logger) {
        boolean hasLogger = logger != null;
        if (onAny) {
            return;
        }
        if (event == Lifecycle.Event.ON_START) {
            if (!hasLogger || logger.approveCall("start", 1)) {
                mReceiver.start();
            }
            return;
        }
        if (event == Lifecycle.Event.ON_STOP) {
            if (!hasLogger || logger.approveCall("stop", 1)) {
                mReceiver.stop();
            }
            return;
        }
    }
}

上面这个就是状态变化时事件分发的基本流程,那么它是如何感知生命周期状态变化的呢?我们调用LifecycleaddObserver()方法,实际调用的是ComponentActivitymLifecycleRegistry对象的方法,而我们关注Activity的生命周期是从onCreate()开始,所以下面看一下ComponentActivityonCreate()方法:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedStateRegistryController.performRestore(savedInstanceState);
    ReportFragment.injectIfNeededIn(this);
    if (mContentLayoutId != 0) {
        setContentView(mContentLayoutId);
    }
}

onCreate()方法中调用了ReportFragmentinjectIfNeedIn()方法。这个方法其实就是往Activity中添加了一个Fragment。而Fragment是依附于Activity的,所以Fragment的生命周期会跟随Activity的生命周期。既然ReportFragment能感知Activity的生命周期,那么它是如何改变状态的?

public class ReportFragment extends Fragment {
    ...
    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
        }
    }
    ...
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

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

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

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        mProcessListener = null;
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        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);
            }
        }
    }
    ...
}

从上面可以看出,在ReportFragment对应的生命周期方法中会调用dispatch()方法,并传递对应的事件Lifecycle.Event.XXX,而dispatch()方法中则是调用了LifecycleRegistryhandleLifecycleEvent()方法。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event);
    moveToState(next);
}

private void moveToState(State next) {
    if (mState == next) {
        return;
    }
    mState = next;
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        mNewEventOccurred = true;
        // we will figure out what to do on upper level.
        return;
    }
    mHandlingEvent = true;
    //状态的变化转化为生命周期事件,然后转发给 LifecycleObserver
    sync();
    mHandlingEvent = false;
}

一图胜千语,下面用一张图来总结大致的流程:


KotlinAndroid

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容