android官方架构组件,Android 架构组件官方文档01——LifeCycle

使用生命周期感知组件处理生命周期

支持生命周期的组件执行操作以响应另一个组件(例如Activity和fragment)的生命周期状态更改。这些组件可帮助您生成组织性更好,并且通常更轻量的代码,这些代码更易于维护。

常见的模式是在Activity和fragment的生命周期方法中实现依赖组件的操作。

但是,这种模式导致代码的组织不良以及错误泛滥。通过使用生命周期感知组件,您可以将相关组件的代码从生命周期方法中移出并移入组件本身。

android.arch.lifecycle包提供了类和接口,可让您构建支持生命周期的组件,这些组件可根据活动或片段的当前生命周期状态自动调整其行为

Android框架中定义的大多数应用程序组件都附带有生命周期。生命周期由操作系统或您的流程中运行的框架代码管理。它们是Android如何工作和应用程序必须尊重它们的核心。不这样做可能会触发内存泄漏甚至应用程序崩溃。

// 如果使用的是java 8要显示声明如下的

def lifecycle_version = "1.1.1"

implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

想象一下,我们有一个在屏幕上显示设备位置的Activity。

常见的实现可能如下所示:

class MyLocationListener {

public MyLocationListener(Context context, Callback callback) {

// ...

}

void start() {

// connect to system location service

}

void stop() {

// disconnect from system location service

}

}

class MyActivity extends AppCompatActivity {

private MyLocationListener myLocationListener;

@Override

public void onCreate(...) {

myLocationListener = new MyLocationListener(this, (location) -> {

// update UI

});

}

@Override

public void onStart() {

super.onStart();

myLocationListener.start();

// manage other components that need to respond

// to the activity lifecycle

}

@Override

public void onStop() {

super.onStop();

myLocationListener.stop();

// manage other components that need to respond

// to the activity lifecycle

}

}

尽管这个示例看起来很好,但在实际的应用程序中,您最终会有太多的调用来管理UI和其他组件,以响应当前的生命周期状态。

管理多个组件会在生命周期方法中放置大量代码,例如onStart()和onStop(),这使得它们很难维护。

此外,无法保证组件在活动或片段停止之前启动。

如果我们需要执行一个长时间运行的操作,比如onStart()中的一些配置检查,情况尤其如此。

这可能会导致onStop()方法在onStart()之前完成的争用条件,从而使组件的存活时间超过所需的时间。

class MyActivity extends AppCompatActivity {

private MyLocationListener myLocationListener;

public void onCreate(...) {

myLocationListener = new MyLocationListener(this, location -> {

// update UI

});

}

@Override

public void onStart() {

super.onStart();

Util.checkUserStatus(result -> {

// what if this callback is invoked AFTER activity is stopped?

if (result) {

myLocationListener.start();

}

});

}

@Override

public void onStop() {

super.onStop();

myLocationListener.stop();

}

}

android.arch.lifecycle包提供的类和接口可帮助您以弹性和独立的方式解决这些问题。

Lifecycle

Lifecycle是一个持有组件生命周期状态(如Activity或Fragment)的信息的类,并允许其他对象观察此状态。

Lifecycle使用两个主要枚举来跟踪其关联组件的生命周期状态:

Event

从框架和Lifecycle类派发的生命周期事件。

这些事件映射到Activities和fragments中的回调事件。

State

由Lifecycle对象跟踪的组件的当前状态。

bV0n8l?w=700&h=381

将状态视为图中的节点,将事件视为这些节点之间的边界。

一个类可以通过向其方法添加注解来监视组件的生命周期状态。

然后,您可以通过调用Lifecycle类的addObserver()方法并传递观察者的实例来添加观察者,如下例所示:

public class MyObserver implements LifecycleObserver {

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)

public void connectListener() {

...

}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)

public void disconnectListener() {

...

}

}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

在上面的例子中,myLifecycleOwner对象实现了LifecycleOwner接口,这将在下一节中介绍。

LifecycleOwner

LifecycleOwner是一个单一的方法接口,表示该类有一个Lifecycle。

它有一个方法getLifecycle(),它必须由class实现。

如果您试图管理整个应用程序进程的生命周期,请参阅ProcessLifecycleOwner。

该接口从各个类(如Fragment和AppCompatActivity)抽象生命周期的所有权,并允许编写与它们一起工作的组件。

任何自定义应用程序类都可以实现LifecycleOwner接口

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

对于位置跟踪示例,我们可以使MyLocationListener类实现LifecycleObserver,然后使用onCreate()方法中的活动生命周期对其进行初始化。

这允许MyLocationListener类是自给自足的,这意味着对生命周期状态变化作出反应的逻辑在MyLocationListener中声明,而不是在活动中声明。

让各个组件存储自己的逻辑使得活动和片段逻辑更容易管理。

class MyActivity extends AppCompatActivity {

private MyLocationListener myLocationListener;

public void onCreate(...) {

myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {

// update UI

});

Util.checkUserStatus(result -> {

if (result) {

myLocationListener.enable();

}

});

}

}

一个常见的用例就是避免在生命周期状处于不好的状态时调用某些回调。

例如,如果回调在保存活动状态后(我自己理解为onSaveInstanceState()方法执行后,也就是fragment不存在)运行fragment事务,则会触发崩溃,因此我们绝不希望调用该回调。

为了简化这个用例,生命周期类允许其他对象查询当前状态。

class MyLocationListener implements LifecycleObserver {

private boolean enabled = false;

public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {

...

}

@OnLifecycleEvent(Lifecycle.Event.ON_START)

void start() {

if (enabled) {

// connect

}

}

public void enable() {

enabled = true;

if (lifecycle.getCurrentState().isAtLeast(STARTED)) {

// connect if not connected

}

}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)

void stop() {

// disconnect if connected

}

}

通过这个实现,我们的LocationListener类完全是生命周期感知的。

如果我们需要使用来自其他Activity或Fragment的LocationListener,我们只需要初始化它。

所有的启动和销毁操作都由该类本身进行管理。

如果Library提供需要与Android生命周期配合使用的类,我们建议您使用支持生命周期的组件。

您的Library客户端可以在客户端无需手动生命周期管理即可轻松集成这些组件。

实施自定义LifecycleOwner

Support Library 26.1.0中的Fragment和Activity以及更高版本已经实现LifecycleOwner接口。

如果您想要创建LifecycleOwner的自定义类,则可以使用LifecycleRegistry类,但需要将事件转发到该类中,如以下代码示例所示:

public class MyActivity extends Activity implements LifecycleOwner {

private LifecycleRegistry mLifecycleRegistry;

@Override

protected void onCreate(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;

}

}

生命周期感知组件的最佳实践

尽可能保持您的UI控制器(Activities和Fragments)尽可能精简。他们不应该试图获取他们自己的数据;相反,使用ViewModel来做到这一点,并观察一个LiveData对象来反映更改回视图。

尝试编写数据驱动UI的界面,其中您的UI控制器的职责是在数据更改时更新视图,或将用户操作通知给ViewModel。

把你的数据逻辑放在ViewModel类中。ViewModel应作为您的UI控制器和其他应用程序之间的连接器。但要小心,ViewModel不负责提取数据(例如,来自网络)。相反,ViewModel应调用相应的组件来获取数据,然后将结果提供给UI控制器。

使用Data Binding在视图和UI控制器之间保持干净的界面。这使您可以使您的视图更具说明性,并最大限度地减少需要在活动和片段中编写的更新代码。如果你喜欢用Java编程语言来做到这一点,可以使用像Butter Knife这样的库来避免样板代码并且有更好的抽象

如果您的UI很复杂,请考虑创建一个presenter类来处理UI修改。这可能是一项艰巨的任务,但它可以使您的UI组件更易于测试。

避免在ViewModel中引用View或Activity上下文。如果ViewModel超出活动(在配置更改的情况下),则活动会泄漏并且垃圾收集器无法正确处理。

支持生命周期感知组件的用例

支持生命周期的组件可以让您在各种情况下更容易地管理生命周期。

一些例子是:

在粗粒度和细粒度 位置更新之间切换。使用生命周期感知组件在位置应用可见时启用细粒度位置更新,并在应用处于后台时切换到粗粒度更新。LiveData是一种生命周期感知型组件,允许您的应用在用户更改位置时自动更新用户界面。

停止并开始视频缓冲。尽可能使用支持生命周期的组件来启动视频缓冲,但延迟播放直到应用程序完全启动。您还可以使用生命周期感知组件在应用程序销毁时终止缓冲。

启动和停止网络连接。使用支持生命周期的组件可以在应用程序处于前台时实时更新(流式传输)网络数据,并在应用程序进入后台时自动暂停。

暂停和恢复动画可绘制。使用生命周期感知组件处理在应用程序处于后台时暂停动画的可绘制画面,并在应用程序处于前景时恢复可绘制画面。

处理停止事件

当Lifecycle属于AppCompatActivity或Fragment时,Lifecycle的状态将更改为CREATED,并在调用AppCompatActivity或Fragment的onSaveInstanceState()时调度ON_STOP事件。

当Fragment或AppCompatActivity的状态通过onSaveInstanceState()保存时,UI被认为是不可变的,直到ON_START被调用。尝试在保存状态后修改UI界面可能会导致应用程序的导航状态不一致,这就是为什么如果应用程序在状态保存后运行FragmentTransaction时FragmentManager会抛出异常。

有关详细信息,详情请参阅 commit()。

如果观察者的关联Lifecycle在STARTED之前,则LiveData通过避免调用其观察者来防止这种边缘情况出现。

在幕后,它决定调用观察者之前调用isAtLeast()。

不幸的是,AppCompatActivity的onStop()方法会在onSaveInstanceState()之后调用,这会在不允许UI状态更改但生命周期尚未移至CREATED状态的情况下留下空隙。

为了防止出现这个问题,beta2版本中的Lifecycle类将lower状态标记为CREATED而不分派事件,即使事件直到onStop()被调用也未被分派,任何检查当前状态的代码也都会获得真实值。

不幸的是,这个解决方案有两个主要问题:

在API等级23或更低的情况下,Android系统实际上保存活动的状态,即使它被另一活动部分覆盖。换句话说,Android系统调用onSaveInstanceState(),但不一定调用onStop()。这会创建一个潜在的长时间间隔,即使其UI状态无​​法修改,观察者仍认为生命周期处于活动状态。

任何想要向LiveData类公开类似行为的类都必须实现Lifecycle beta2和更低版本提供的解决方法

注意:为了使此流程更简单,并提供与旧版本的更好兼容性,从版本1.0.0-rc1开始,在调用onSaveInstanceState()而无需等待对onStop()的调用时,将Lifecycle对象标记为CREATED,并调度onStop()方法。这不太可能影响您的代码,但您需要注意这一点,因为它与API级别26及更低级别的Activity类中的调用顺序不匹配。

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

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

相关文章

C语言的核心和灵魂

点击蓝字关注我们提起C语言大部分开发者很自然就会想到指针二字,没错,作为C的核心和灵魂,它的地位咱们就不再赘述了。今天我们想跟大家讲的是指针中的两个特有名词:“悬空指针”和“野指针”。悬空指针C语言中的指针可以指向一块内…

javaone_JavaOne 2015 –提交技巧和建议

javaone大家都知道JavaOne 。 感觉就像一直存在。 而且,即使我们跌宕起伏,而地理位置也不是我们想要的那样,旧金山也很昂贵,而且和。 这是有关各种Java的顶级会议。 今年又再次成为程序委员会(“ Java,DevO…

C语言_结构体总结,附实例源码

点击蓝字关注我们当前文章介绍动态堆空间内存分配与释放,C语言结构体定义、初始化、赋值、结构体数组、结构体指针的相关知识点,最后通过一个学生管理系统综合练习结构体数组的使用。1. 动态内存管理C语言代码----->编译----->链接------>可执行…

四大C语言知识总结

点击蓝字关注我们1、#define宏定义以#号开头的都是编译预处理指令,它们不是C语言的成分,但是C程序离不开它们,#define用来定义一个宏,程序在预处理阶段将用define定义的来内容进行了替换。因此在程序运行时,常量表中并…

jdbc select语句_SELECT语句使用JDBC和Hibernate批量获取

jdbc select语句介绍 现在,我已经介绍了Hibernate对INSERT , UPDATE和DELETE语句的批处理支持,是时候分析SELECT语句结果集的批量提取了。 JDBC ResultSet提供了一个客户端Proxy游标,用于获取当前语句的返回数据。 执行该语句后&…

看懂开源项目,你得熟悉这几个 C++11 新特性

点击蓝字关注我们C11 中增加了许多的新特性。在本文中,我们来聊一下 lambda 表达式,闭包,std::function以及std::bind。lambda 表达式C11 中新增了 lambda 表达式这一语言特性。lambda 表达式可以让我们快速和便捷的创建一个 “函数”。下面是…

5元素升级android6,【五元素ifive X.7】无障碍升级,ifveX详细升级固件教程,快为爱机升级吧。...

android系统的乐趣就是可以随意的刷机,所以拿到如此高配置的ifiveX也是想随时体验最新的android系统。而很多朋友可能只会用设备,刷机这种比较技术性的动作就不太会弄了。也就在这周,才帮同事刷RUU把已经无法启动的G12刷了回来。所以刷机还是…

昆仑通态复制的程序可以用吗_昆仑通态专题(七):MCGS组态软件的设备窗口...

点击上方蓝色字体,关注我们设备窗口是MCGS嵌入版组态软件系统的重要组成部分,在设备窗口中建立系统与外部硬件设备的连接关系,使系统能够从外部设备读取数据并控制外部设备的工作状态,实现对工业过程设备的实时监控与操作。01 设备…

嵌入式C语言程序调试和宏使用的技巧

点击蓝字关注我们01.调试相关的宏在Linux使用gcc编译程序的时候,对于调试的语句还具有一些特殊的语法。gcc编译的过程中,会生成一些宏,可以使用这些宏分别打印当前源文件的信息,主要内容是当前的文件、当前运行的函数和当前的程序…

matlab中欠定方程组超定方程组_《数值天气预报》:球坐标系中的基本方程组

人们是如何预报天气的?目前的预报方法主要有两种:一种是基于由各种探测资料绘制的天气图,结合历史资料进行分析预测;另一种是基于大气方程组,利用数值解法对其进行求解,从而得到未来时刻的大气状态。后者就…

浏览器总是跳转到缓存界面_跳转到企业缓存之前要考虑的事项

浏览器总是跳转到缓存界面介绍 关系数据库事务是ACID ,强大的一致性模型简化了应用程序开发。 由于启用Hibernate缓存是一项配置 ,因此,只要数据访问层开始出现性能问题,就转向缓存非常吸引人。 添加缓存层确实可以提高应用程序性…

CryptoTab 服务器_如何架设FTP服务器,如何架设FTP服务器,具体架设方法

FTP服务器,则是在互联网上提供存储空间的计算机,它们依照FTP协议提供服务。 FTP的全称是File Transfer Protocol(文件传输协议)。顾名思义,就是专门用来传输文件的协议。简单地说,支持FTP协议的服务器就是FTP服务器。那么&#xf…

C语言和C++的区别和联系

点击蓝字关注我们C语言和C到底是什么关系?首先C和C语言本来就是两种不同的编程语言,但C确实是对C语言的扩充和延伸,并且对C语言提供后向兼容的能力。对于有些人说的C完全就包含了C语言的说法也并没有错。C一开始被本贾尼斯特劳斯特卢普&#…

hibernate语句_如何优化Hibernate EllementCollection语句

hibernate语句介绍 Hibernate支持三种数据映射类型 : 基本 (例如String,int), Embeddable和Entity 。 通常,数据库行被映射到Entity ,每个数据库列都与一个基本属性相关联。 当将多个字段映射组…

C++ 虚函数表剖析

点击蓝字关注我们一、概述为了实现C的多态,C使用了一种动态绑定的技术。这个技术的核心是虚函数表(下文简称虚表)。本文介绍虚函数表是如何实现动态绑定的。二、类的虚表每个包含了虚函数的类都包含一个虚表。我们知道,当一个类&a…

aix pax_通过Pax考试对JBoss Fuse 6.x进行集成测试,第一部分

aix paxJBoss Fuse是一个功能强大的分布式集成平台,具有内置功能,可用于针对集成的微服务部署进行集中式配置管理,服务发现,版本控制,API网关,负载平衡,故障转移等。 JBoss Fuse 6.x构建在Fabri…

android王者调不了界面,王者荣耀登录界面怎么改?登录界面更改教程[多图]

王者荣耀登录界面怎么改?许多玩家都想更改自己登陆的界面,但是都不清楚,下面就让安卓乐园小编为大家带来,登录界面更改教程。王者荣耀登录界面怎么改?1、安卓手机打开文件管理,找到根目录下Android/data/co…

y空间兑换代码_Python爬虫实战:QQ空间全自动点赞工具

QQ空间自动点赞前景提要目标确定分析介绍登陆获取cookie寻找XML寻找可变参数获取第一个空间动态寻找点赞所需的URL寻找可变参数功能提升到秒赞全部代码最后还是希望你们能给我点一波小小的关注。奉上自己诚挚的爱心私信小编01即可获取大量Python学习资料前景提要因为我周围的小…

学点 STL C++ 无序容器和元组

点击蓝字关注我们无序容器我们已经熟知了传统 C 中的有序容器 std::map/std::set&#xff0c;这些元素内部通过红黑树进行实现&#xff0c; 插入和搜索的平均复杂度均为 O(log(size))。在插入元素时候&#xff0c;会根据 < 操作符比较元素大小并判断元素是否相同&#xff0c…

html中的文档格式及举例,跟我一起从零开始学习WebAssembly(三)、最简单的例子hello world(使用自定义HTML模板)...

文章目录创建C代码片创建我们的自定义HTML模板文件编译运行实例有时我们想要使用我们自定义HTML模板。让我们来看看我们如何做到这一点。创建C代码片首先&#xff0c;创建一个名为hello2的目录。其次&#xff0c;在该目录下创建一个名为hello2.c文件。并将以下C代码保存在文件中…