文档章节

Android Architecture Components之处理生命周期

dj_归去来兮
 dj_归去来兮
发布于 2017/08/14 15:49
字数 1560
阅读 11
收藏 0
点赞 0
评论 0

包  android.arch.lifecycle 提供了类和接口让你构建拥有生命周期的组件--可以根据activity或者fragment的生命周期做出调整的组件。

大部分的APP组件都是在Android框架中定义的,都会有生命周期。这些生命周期过程被操作系统或者框架代码管理着。它们是Android运行的核心,你的应用必须遵守它们。不这样做可能会引起内存泄漏或者应用挂掉。

想想一下,我们有个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;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
  }

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

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

尽管这个示例看起来没毛病,在真实的APP开发中,你对onStart()、 onStop()方法有太多的调用,这会导致代码非常臃肿。

此外,有些组件不会在onStart()方法中就已经处于started状态了。如果我们需要在开始观察位置之前检查一些配置将会发生什么呢?有些情况是这样的:在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();
    }
}

包 android.arch.lifecycle 提供了类和接口帮助你通过富有弹性和独立的方式解决这些问题。

Lifecycle

Lifecycle 类持有关于activity或者fragment等组件的生命周期状态,允许其他对象观察这些状态。

Lifecycle 使用两个主要的枚举跟踪关联的组件的生命周期。

Event:这些生命周期事件由框架和 Lifecycle发送。这些事件与activities和fragments回调事件一 一对应。

State: Lifecycle 对象追踪的组件的当前状态。

设想state是图表中的节点,event是两个节点之间的边框线。

通过在方法上加上注解,可以让一个类监控组件的生命周期。

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是一个函数式接口,表示实现类有生命周期。只有一个方法:getLifecycle(),需要被子类实现。

这个类从个体类(activity,fragment)中抽象了生命周期的所有权,允许编写可以与它们一起工作的组件。任何一个自定义的应用类都可以实现这个接口。

针对上面的示例,我们可以使我们的MyLocationListener 类称为一个 LifecycleObserver ,然后通过 Lifecycle 的方法onCreate初始化它。

class MyActivity extends LifecycleActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}

如果当前 Lifecycle不是处在一个良好的状态,通常情况下要避免调用特定的回调方法。例如,在activity的onSaveInstance方法调用之后,调用了运行fragment事物的回调方法,将会导致奔溃,所以,我们不要去调用那个回调方法。

为了让这个方案易于使用,Lifecycle 类允许其他对象查询当前状态。

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

这个实现,我们的 LocationListener 类是有完整的生命周期。它可以不用通过管理自己的activity对自己初始化和清除工作。如果我们需要从另外一个activity或者另外一个fragment使用LocationListener ,我们只需要初始化它就行了。全部的设置和数据清除的操作全部由自己来完成。

可以和 Lifecycle 协同工作的类称为有生命周期的组件。提供与Android生命周期协同工作的类的类库推荐对外提供有生命周期的组件,以便它们的调用客户端不用手动管理生命周期,从而易于集成。

LiveData是有生命周期的组件的一个例子。将 LiveData和 ViewModel一起使用,更易于在遵循Android生命周期的情况下使用数据填充UI层。

Best practices for Lifecycles

    1 保持你的UI控制层(activities,fragments)越轻越好。它们不应该自己去取数据,相反,使用一个 ViewModel去做,并且观察 LiveData 反应到UI层上。

    2 尝试编写数据驱动UI,当数据变化时,你的UI层控制器负责更新控件,或者通知用户操作到ViewModel

    3 把数据操作逻辑放在ViewModel 类中,ViewModel 应该像UI层与其他APP组件之间的连接器。不过,要小心,获取数据(例如,从网路获取数据)并不是ViewModel 的责任。ViewModel 应该调用适当的组件去做这个工作,然后提供结果给UI层控制器。

    4 使用Data Binding在控件和控制器之间保持干净的接口。这允许在activity和fragment中,你把你的控件更声明化(声明性编程),并且更新最少的代码。

    5 如果你的UI很复杂,考虑创建一个presenter类持有UI的变化。这通常过度封装了,但是可以让UI层的测试更加容易。

    6 决不要在 ViewModel 层引用 View 或者Activity 上下文。如果ViewModel比activity的生命周期长的话,activity将会内存泄漏,不能正确的GC。

 

Addendum

Implementing LifecycleOwner in custom activities and fragments

任何一个自定义的fragment和activity都可以通过实现内建的LifecycleRegistryOwner 接口变成LifecycleOwner,而不是继承 LifecycleFragment 或者 LifecycleActivity

public class MyFragment extends Fragment implements LifecycleRegistryOwner {
    LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}

如果你有个自定义的想要变成 LifecycleOwner 的类,你可以使用 LifecycleRegistry 类,但是你需要转发事件到这个类中。如果他们实现了 LifecycleRegistryOwner 接口,这个事件转发对fragments,activities会自动的进行。

来自 https://developer.android.google.cn/topic/libraries/architecture/lifecycle.html

© 著作权归作者所有

共有 人打赏支持
dj_归去来兮
粉丝 14
博文 88
码字总数 31620
作品 0
合肥
Android工程师
使用Kotlin高效地开发Android App(四)

一. 运算符重载 在Kotlin的世界里,我们可以重载算数运算符,包括一元运算符、二元运算符和复合赋值运算符。 使用operator修饰符来修饰函数名的函数,这些函数可以是成员函数也可以是扩展函数...

fengzhizi715 ⋅ 05/25 ⋅ 0

架构组件之--ViewModel

前言:这是自己的的第一篇文章,希望可以把自己所学到的东西都能总结并分享出来,希望可以做好。 一、简介 2017Google I/O大会上google引入了lifeCycle组件,说来惭愧,最近才来使用,这也是...

墨迹_T ⋅ 05/27 ⋅ 0

Android Jetpack 助推应用开发 | 中文字幕视频介绍

Android Jetpack 能帮助您加快应用开发速度,处理类似后台任务、UI 导航以及生命周期管理之类的活动,免去开发者编写样板代码的麻烦,专注提升应用体验。这次发布的 Android Jetpack 组件覆盖...

Android_开发者 ⋅ 05/14 ⋅ 0

老生常谈Android的MVP架构

原生框架问题 由于原生 Android 开发应该已经是一个基础的 MVC 框架,所以在初始开发的时候并没有遇到太多框架上的问题,可是一旦项目规模到了一定的程度,就需要对整个项目的代码结构做一个...

LaxusJ ⋅ 04/23 ⋅ 0

Architecture Components MVVM架构演进

在对MVP的架构实践中,发现写单元测试不是那么方便,因为Presenter持有了View的引用,而Mock View的 行为和方法特别的卡慢,因此只能把具体的业务逻辑再抽成一个个独立于Presenter的Logic,进...

Mr云台 ⋅ 2017/11/27 ⋅ 0

Android Architecture Components 之LiveData, ViewModel

一 入口 阅读源码需要从源码的入口处着手,先看先官方的例子(https://developer.android.com/topic/libraries/architecture/livedata): ViewModel 里面有一个LiveData数据和getLivedata方法...

nothingwxq ⋅ 05/22 ⋅ 0

[译] 支持库 27.1.0 中的 Loader

原文地址:Loaders in Support Library 27.1.0 原文作者:Ian Lake 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:dreamhb 校对者:Starriers 为了 支持库 27.1.0,...

Android_开发者 ⋅ 05/24 ⋅ 0

我的Android重构之旅:框架篇

在我这几年的学习和成长中,慢慢的意识到搭建一个优秀的 Android 开发框架是一件非常困难以及痛苦的事情,它不仅需要满足不断增长的业务需求,还要保证框架自身的整洁与扩展性,这让事情变得...

codeGoogle ⋅ 06/13 ⋅ 0

[翻译] Android Architecture 之 LiveData

LiveData是一个可观察的数据持有类,不像通常的可观察者,LiveData是可感知生命周期的,这意味着LiveData只更新处于活动生命周期状态的组件中的观察者。 LiveData更新的话只会通知处于活动状...

小菜鸟程序媛 ⋅ 06/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Qt中的坑--QTreeWidget添加item 不能显示出来

QTreeWidget* pTree = ui.TreeCheckList; QTreeWidgetItem* item = new QTreeWidgetItem(pTree) ;item->setText ( 0, "test" );pTree->addTopLevelItem (item ); 原因是因为创建一个......

k91191 ⋅ 18分钟前 ⋅ 0

使用Guava的RateLimiter做限流

场景: 1. 在日常生活中,我们肯定收到过不少不少这样的短信,“京东最新优惠卷…”,“天猫送您…”。这种类型的短信是属于推广性质的短信。这种短信一般群发量会到千万级别。然而,要完成这...

wind2012 ⋅ 18分钟前 ⋅ 0

QSlider重新enterEvent

#ifndef DIALOG_H#define DIALOG_H#include <QDialog>namespace Ui {class Dialog;}class Dialog : public QDialog{ Q_OBJECTpublic: explicit Dialog(QW......

xxdd ⋅ 18分钟前 ⋅ 0

生产环境redis备份与恢复

生产环境redis备份与恢复 Tyrant0532 0人评论 1563人阅读 2018-02-01 20:34:10 redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。生产中我们主...

rootliu ⋅ 20分钟前 ⋅ 0

nginx中出现403forbidden错误

nginx “403 Forbidden” 错误 出现这个错误一般是因为以下原因: 网站禁止特定的用户访问所有内容,例:网站屏蔽某个ip访问。 访问禁止目录浏览的目录,例:设置autoindex off后访问目录。 ...

河图再现 ⋅ 21分钟前 ⋅ 0

上海云栖:金融政企行业的CDN最佳实践

摘要: 在刚刚结束的上海云栖大会飞天技术汇分论坛上,阿里云视频云产品架构师罗小飞进行了《阿里云CDN——面向金融政企的CDN最佳实践》主题分享,为上海的嘉宾介绍CDN的解决方案与技术服务体...

猫耳m ⋅ 26分钟前 ⋅ 0

docker 基本操作

docker介绍 Docker项目提供了构建在Linux内核功能之上,协同在一起的的高级工具。其目标是帮助开发和运维人员更容易地跨系统跨主机交付应用程序和他们的依赖。Docker通过Docker容器,一个安全...

haoyuehong ⋅ 27分钟前 ⋅ 0

上海云栖:金融政企行业的CDN最佳实践

摘要: 在刚刚结束的上海云栖大会飞天技术汇分论坛上,阿里云视频云产品架构师罗小飞进行了《阿里云CDN——面向金融政企的CDN最佳实践》主题分享,为上海的嘉宾介绍CDN的解决方案与技术服务体...

阿里云云栖社区 ⋅ 30分钟前 ⋅ 0

安装与配置hadoop

一、CentOS7安装 java8,参考centos7.0 安装java1.8,tomcat 二、安装hadoop 版本V3.03 1、下载并解压hadoop # mkdir /usr/local/app# mkdir /usr/local/app/hadoop# cd /usr/local/app/had......

iturtle ⋅ 31分钟前 ⋅ 0

Idea设置Serializable自动生成

File --> Settings --> Editor --> Inspections ->Serialization issues,在该项下找到“Serializable class without 'serialVersionUID' ”并勾选...

Gmupload ⋅ 34分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部