Android Lifecycle框架介绍

概览

本篇主要介绍有关于Lifecycle

Lifecycle 是属于 Android Architecture Components 的一个组件, 而Android Architecture Components是属于Android Jetpack的一部分, 可以让组件自己管理生命周期的逻辑,避免每次调用时的繁琐步骤,用Lifecycle实现的组件可以实现生命周期的监听,数据变化的监听等功能。

关于Android Architecture Components

Android Architecture Components 主要包含以下的组件

  • Room (用于数据持久化)
  • Lifecycle-aware components (能感知生命周期的组件)
  • ViewModels (用于存储和UI关联的数据,不会随设备旋转销毁)
  • LiveData (用于监听数据变化)
  • Navigation (用于应用内导航,可视化)
  • Paging (用于分页加载数据)
  • WorkManager (可用于创建定时启动的异步任务)

这些组件可以帮助开发者能用更少的代码更高效的开发应用。

Lifecycle集成

首先从怎么集成开始

第一步:

在build.gradle中增加google()的repo

allprojects {
    repositories {
        jcenter()
        google()
    }
}

第二步:

添加依赖

Java

    // Lifecyle的版本,现在最新的是1.1.1
    def lifecycle_version = "1.1.1"

    // ViewModel 和 LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // 仅用 ViewModel
    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
    // 仅用 LiveData
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"
    //  仅仅支持Lifecycle, 不包含LifeModel和LiveData
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"

    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    // 如果用的是java8使用以下的依赖
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

    // LiveData 的 ReactiveStreams插件
    implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"

    // LiveData测试
    testImplementation "android.arch.core:core-testing:$lifecycle_version"

Kotlin

    // Lifecyle的版本,现在最新的是1.1.1
    def lifecycle_version = "1.1.1"

    // ViewModel 和 LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // 仅用 ViewModel
    implementation "android.arch.lifecycle:viewmodel-ktx:$lifecycle_version" // use -ktx for Kotlin
    // alternatively - just LiveData
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"
    //  仅仅支持Lifecycle, 不包含LifeModel和LiveData
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"

    kapt "android.arch.lifecycle:compiler:$lifecycle_version"
    // 如果用的是java8使用以下的依赖
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

    // LiveData 的 ReactiveStreams插件
    implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"

    // LiveData测试
    testImplementation "android.arch.core:core-testing:$lifecycle_version"

为什么会引入Lifecycle

举个🌰

我们在应用中有使用地图跟踪用户的地理位置,地理位置的更新在一个listener里。

于是就有了如下的代码:

public void onStart() {
    super.onStart();
    myLocationListener.start();
}

public void onStop() {
    super.onStop();
    myLocationListener.stop();
}

这样写并不会有问题,但是会有以下两个问题可能出现:

1、如果在onStart里有一个较为耗时的block存在,在运行的过程中用户退出了程序,就会在这个block运行时提前退出Activity, 这个问题就很难被定位到。

public void onStart() {
    super.onStart();
    // 一个较为耗时的检查用户状态的block
    Util.checkUserStatus(result -> {
        // what if this callback is invoked AFTER activity is stopped?
        if (result) {
            myLocationListener.start();
        }
    });
}

public void onStop() {
    super.onStop();
    myLocationListener.stop();
}

2、如果在一个Activity内有较多的linstener需要像上面的🌰一样在onStart和onStop中管理,就会造成这两个地方的代码变得多而难以维护,如果忘掉一两个也很难一下子看出来。

怎么解决这个问题?

如果组件能够感知到Activity或者Fragment的变化,那么就可以在组件内部追踪Activity或者Fragment的生命周期,将之前写在Activity或者Fragment里的代码写到组件的内部。

要解决这个问题,我们首先来看看android.arch.lifecycle包中为我们提供了哪些弹药:

Lifecycle类

Lifecycle类持有组件的可监听的生命周期的状态,通过Event和State两个枚举来体现关联的生命周期的状态。

Event包含ON_ANY, ON_CREATE, ON_DESTROY, ON_PAUSE, ON_RESUME, ON_START, ON_STOP 这些枚举值

可以通过使用注解OnLifecycleEvent来定义某个方法会响应某种State状态,例如:

public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

State包含CREATED, DESTROYED, INITIALIZED, RESUMED, STARTED 这些枚举值, 在实现了LifecycleOwner接口的类中可以通过以下代码获得当前的State:

if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {

}

关于LifecycleOwner接口

· Support Library 26.1.0之后的Fragments和Activity都已经继承了LifecycleOwner接口,如AppCompatActivity和Fragment都已经继承LifecycleOwner接口, 但是Activity类并没有实现这个接口,如果想要使用lifecycle的特性,可以自己手动即成LifecycleOwner接口:

import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LifecycleRegistry;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class CustomLifecycleActivity extends Activity implements LifecycleOwner {

    private LifecycleRegistry mLifecycleRegistry;

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

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

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

Lifecycle的组件和使用场景

  • LiveData 假设你的应用需要应用在前台的时候在地图上更新精细坐标,而程序进入后台只需要更新大致的位置(频率、精度不高的位置),那么使用LiveData可以在位置变化的时候自动更新UI

  • 假设你在开发一款在线播放视频的应用, 需要程序在进入前台的时候立即开始获取数据,当程序完全启动后开始恢复之前的播放,也可以让程序进入后台或者销毁后停止获取视频流

  • 程序在前台时实时更新网络状态,进入后台马上停止监听

  • 进入后台立即停止动画,进入前台立即恢复动画

总结

1、 Support Library 26.1.0之后的Fragments和Activity都已经继承了LifecycleOwner接口, 所以可以直接获得当前的State, 当onSaveInstanceState()执行时就会更新Lifecycle的State.

2、 通过实现LifecycleOwner接口可以将不支持Lifecycle的组件手动支持Lifecycle

3、@OnLifecycleEvent 可以在继承了LifecycleObserver的Listener中的方法中通过注解的方式告诉Listner在哪个Event状态时去执行某个方法。

4、通过Listener结合LifecycleObserver可以将Activity或者Fragment中的生命周期管理的代码写到Listener内部,避免了每次调用时重复写管理生命周期方法的繁琐步骤。

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