Android官方架构组件介绍之LifeCycle

下面是官方提供的Android App开发的架构图:

从上图可以看到一些关键字:ViewModel,LiveData,Room等。其实看了上面视频的会发现Google官方Android架构组件一共包括以下几个:

  • LifeCycle : 与Activity和Fragment的生命周期有关
  • LiveData :异步可订阅数据,也是生命周期感知
  • ViewModel :视图数据持有模型,也是生命周期感知
  • Room :SQLite抽象层,用于简化SQLite数据存储

这篇文章主要讲解LifeCycle在项目的简单用法

AS中添加依赖

首先在工程根目录的build.gradle中添加一下内容:

allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' } //添加此行
}
}

然后在应用目录下的build.gradle中添加以下依赖:

//For Lifecycles, LiveData, and ViewModel
compile "android.arch.lifecycle:runtime:1.0.0-alpha1"
compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1" //For Room
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"

LifeCycle相关使用

在我们平时的项目中经常会遇到很多需要依赖生命周期的逻辑处理,比如有这么一个需求。
在某个Activity我们需要在屏幕上展现用户的地理位置。简单的实现方法如下:

lass 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; public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// update UI
});
} public void onStart() {
super.onStart();
myLocationListener.start();
} public void onStop() {
super.onStop();
myLocationListener.stop();
}
}

虽然以上代码看起来很简洁,但在实际项目中的onStart,onStop方法可能会变得相当庞大。
此外,实际情况可能并不像上面这么简单,例如我们需要在start位置监听前做用户状态检测,检测是一个耗时的任务,那么很有可能在检测结束前用户提前退出了Activity,这时候就会导致myLocationListener.start()myLocationListener.stop()后面调用,从而引起很多难以定位的问题。代码如下:

class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener; public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// update UI
});
} public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start();
}
});
} public void onStop() {
super.onStop();
myLocationListener.stop();
}
}

这时候就该今天的主角LifeCycle出场了。它提供了一套接口帮助你处理这些问题。

LifeCycle

LifeCyle类持有Activity或者Fragment的生命周期相关信息,并且支持其他对象监听这些状态。

LifeCyle有两个枚举用于追踪生命周期中的状态。

Event

这是生命周期的事件类,会在Framework和LifeCycle间传递,这些事件映射到Activity和Fragment的回调事件中。

State

LifeCycle所持有Activity或Fragment的当前状态。

一个类想要监听LifeCycle的状态,只需要给其方法加上注解:

public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
} @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
}
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());

LifeCycleOwner

LifeCycleOwner是一个只有一个方法的接口用于表明其有一个LifeCycle对象。这个方法为getLifecycle()
这个对象给Acitivity,Fragment和LifeCycle提供了一个很好的抽象关系,Activity和Fragment只要实现这个接口就能配合LifeCycle实现生命周期监听。

注意:由于目前LifeCycle处于alpha阶段,所以Fragment和AppCompatActivity并不会实现这些方法,在此之前,可以使用LifecycleActivityLifecycleFragment。等LifeCycle趋于稳定后,Fragment和AppCompatActivity会默认实现这些。

对于之前的位置监听的例子,我们可以让MyLocationListener继承LifecycleObserver,在onCreate中使用LifeCycle进行初始化,剩下的问题则不必担心了。因为MyLocationListener有能力进行生命周期的判断。

class MyActivity extends LifecycleActivity {
private MyLocationListener myLocationListener; public void onCreate(...) {
//此处进行初始化getLifecycle()传入LifeCycle对象
myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// update UI
});
//检测用户状态并启用监听
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.enable();
}
});
}
}

下面看一下MyLocationListener

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.getState().isAtLeast(STARTED)) {
// connect if not connected
}
} @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// disconnect if connected
}
}

LifeCycle最重要的特性就是在⓵处,他可以提供主动查询生命周期状态的方法。这样就避免了上面遇到的myLocationListener.start()myLocationListener.stop()后面调用的问题。

通过以上的实现,我们的LocationListener是完全的生命周期感知了,它可以进行自己的初始化和资源清理而不必受Activity或者Fragment的管理。这时候如果我们在其他Activity或者Fragment中使用LocationListener,我们只需要初始化它就行了,不必再担心生命周期对它的影响,因为它内部会做好这一切。

通过LefeCycle工作的类我们称之为生命周期感知。鼓励需要使用Android生命周期的类的库提供生命周期感知组件,以便客户端可以轻松地在客户端上集成这些类,而无需手动生命周期管理。

LiveData就是生命周期感知组件的示例,将LiveData和ViewModel一起使用,可以在遵循Android生命周期的情况下,更容易的使用数据来填充UI。

生命周期的最佳实践

  • 保持你的UI(Activity和Fragment)尽可能简洁。它们不应该试图获取它们的数据而是使用ViewModel来执行此操作,并通过LiveData的回调将数据更新到UI中。
  • 尝试编写数据驱动的UI,你的UI的责任是在数据更改时更新视图,或将用户操作通知给ViewModel。
  • 将你的数据逻辑放在ViewModel类中。 ViewModel应该作为UI和其他数据操作的连接器。值得注意的是,ViewModel并不负责提取数据(例如,从网络)。相反,ViewModel应该调用其他接口来执行此工作,然后将结果提供给UI。
  • 使用Data Binding可以让你的的UI代码变得相当干净利落。这将使你的UI更具声明性,并最大限度地减少书写UI更新的代码。如果您更喜欢在Java中执行此操作,请使用像Butter Knife这样的库来避免使用样板代码并进行更好的抽象。
  • 如果你有一个复杂的UI,请考虑创建一个Presenter类来处理UI修改。这通常是过度架构的,但可能有助于使你的UI更容易测试。
  • 不要在ViewModel中引用View或Activity上下文。如果ViewModel在Activity或View销毁的情况下依旧存活,这时将导致内存泄漏。

补充

在自定义的Activity或Fragment中实现LifeCycleOwner,可以实现LifecycleRegistryOwner这个接口。而不是继承(LifeCycleFragment和LifeCycleActivity)

public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this); @Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}

如果你要在自定义的类中实现LifeCycleOwner,可以使用LifecycleRegistry,但是你需要主动向其转发生命周期的事件。但如果你自定义类是Fragment和Activity的话并且它们实现的是LifecycleRegistryOwner,那么事件转发都是自动完成的。

Android官方架构组件介绍之LifeCycle(一)的更多相关文章

  1. Android官方架构组件介绍之LifeCycle

    Google 2017 I/O开发者大会于近日召开,在开发者大会上谷歌除了发布了Android O等一些新产品之外,也对Android代码的架构做出了一个官方的回应. Google 2017 I/O开 ...

  2. Android官方架构组件介绍之ViewModel

    ViewModel 像Activity,Fragment这类应用组件都有自己的生命周期并且是被Android的Framework所管理的.Framework可能会根据用户的一些操作和设备的状态对Act ...

  3. Android官方架构组件介绍之LiveData

    LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...

  4. Android官方架构组件介绍之ViewModel(三)

    ViewModel 像Activity,Fragment这类应用组件都有自己的生命周期并且是被Android的Framework所管理的.Framework可能会根据用户的一些操作和设备的状态对Act ...

  5. Android官方架构组件介绍之LiveData(二)

    LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...

  6. Android官方架构组件介绍之应用(四)

    讲一个项目常见的功能,友盟统计功能 例如一个项目有很多多modlue,每个里面modlue都有Activity,Activity需要友盟统一,Fragment也需要友盟统计.一般做法就是继承一个Bas ...

  7. 改造 Android 官方架构组件 ViewModel

    前言 Android 官方架构组件在今年 5 月份 Google I/O 大会上被公布, 直到 11 月份一直都是测试版, 由于工作比较繁忙, 期间我只是看过类似的文章, 但没有在实际项目中使用过, ...

  8. Android官方架构组件指南

    此指南适用于那些曾经或现在进行Android应用的基础开发,并希望了解和学习编写Android程序的最佳实践和架构.通过学习来构建强大的生产级别的应用. 注意:此指南默认你对Android开发有比较深 ...

  9. Jetpack架构组件学习(1)——LifeCycle的使用

    原文地址:Jetpack架构组件学习(1)--LifeCycle的使用 | Stars-One的杂货小窝 要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 最近 ...

随机推荐

  1. 断电操作导致的jboss项目部署失败------从早上九点一直到下午4点才解决

    虚拟机jboss可以连接成功,项目也可以正常编译成功.但是,去访问backstop网址的时候,就是,显示,无法访问该网站.访问9990的jboss服务器时,也是显示无法访问该网站. 项目代码是没问题的 ...

  2. DBUtils工具类和DBCP连接池

    今日内容介绍 1.DBUtils2.处理结果集的八种方式3.连接池4.连接池的用法1 PrepareStatement接口预编译SQL语句 1.1 预处理对象 * 使用PreparedStatemen ...

  3. Java分层概念(转)

    Java分层概念(转) 对于分层的概念,似乎之间简单的三层,多了,就有点难以区分了,所以收藏了这个. ervice是业务层 action层即作为控制器 DAO (Data Access Object) ...

  4. 通配符的匹配很全面, 但无法找到元素 'tx:annotation-driven'

    配置Spring时出现如题这个错误,下面是xml的内容 <?xml version="1.0" encoding="UTF-8"?> <bea ...

  5. Java50道经典习题-程序28 排序算法

    题目:对10个数进行排序分析:可以利用选择法,即从后9个比较过程中,选择一个最小的与第一个元素交换, 下次类推,即用第二个元素与后8个进行比较,并进行交换. public class Prog28 { ...

  6. 【Arcgis for android】保存地图截图到sd卡

    关键词:arcgis for android ,截图,bitmap,sd卡 参考文章:http://blog.csdn.net/wozaifeiyang0/article/details/767972 ...

  7. 微信开放平台 redirect_uri参数错误

    微信开放平台 redirect_uri参数错误   请注意是开放平台开放平台,公众平台和开放平台不是同一个. 解决办法 在写 授权回调域 时,地址只用写到域名级,不能写到域名下一级,这和QQ互联的回调 ...

  8. EXCEL跨表比较两列,并填充新值背景

    Sub FillNewToYellow() Dim dic Dim oldArr(), updatedArr() On Error Resume Next If Worksheets("ol ...

  9. gRPC官方文档(概念)

    文章来自gRPC 官方文档中文版 gRPC 概念 本文档通过对于 gRPC 的架构和 RPC 生命周期的概览来介绍 gRPC 的主要概念.本文是在假设你已经读过文档部分的前提下展开的.针对具体语言细节 ...

  10. 正经学C#_判断[IF语句]:[c#入门经典]

    判断语句几乎是最为常用的语句之一,是最有效的. 先说IF语句,IF语句也是属于分支的一种,用来控制流程的. IF的语句是这样的 IF(xxx 条件) { //代码块 } ,b; ) { b=a--; ...