数据管理

对于仅仅读数据。一种经常使用的管理模式是在onCreate函数中进行数据的载入,直到组件的onDestory函数被调用时在进行释放。

    // 缓存仅仅读的数据
private Object readOnlyData; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 读取数据到内存
readOnlyData = readOnlyData();
} private Object readOnlyData() {
return null ;
} @Override
protected void onDestroy() {
super.onDestroy();
// 将数据置空,加速回收
readOnlyData = null ;
}

假设数据支持读写操作。则须要在onResume或者onCreate中进行读取,而在onPause中实现存储。

由于当onPause函数被调用后,该界面组件就处于可回收的状态。当资源紧张时,系统会强行销毁组件对象。

对象中全部未持久化的改动就会丢失。

对于读写数据处理的模型示比例如以下:

    // 缓存可读写的数据
private Object data; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 读取数据到内存
data = readData();
} @Override
protected void onResume() {
super.onResume();
data = readData();
} private Object readData() {
// TODO 读取数据
return null ;
} private void writeData(Object data) {
// TODO 写入数据
} @Override
protected void onPause() {
super.onPause();
writeData( data);
} @Override
protected void onDestroy() {
super.onDestroy();
// 将数据置空。加速回收
data = null ;
}

状态管理

当系统将界面组件切离前台状态(即onPause函数调用前),会先行调用onSavaInstanceState函数。在该函数中,开发人员能够讲组件中的状态数据写入參数的outState对象中。outState的对象类型是Bundle,他是通过键值对的方式进行数据的存储。

onCreate —— 假设含有state数据。则先调用onRestoreInstanceState。

onRestoreInstanceState —— 组件进入前台状态前,先调用恢复数据。

onSaveInstanceState —— 组件离开前台状态,先调用状态保存数据。在调用onPause。

假设用户是主动离开前台状态。则不会触发该状态。

    boolean       needSaveDraft = true;

    // 假设是非主动离开时。则会调用onSaveInstanceState
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 先保存改动状态。用于恢复启动时恢复该信息
outState.putBoolean( "NEED_SAVE_DRAFT", needSaveDraft );
// 表示在被动退出时无需保存
needSaveDraft = false ;
} @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
needSaveDraft = savedInstanceState.getBoolean("NEED_SAVE_DRAFT" );
}
} @Override
protected void onPause() {
super.onPause();
// 假设不是被动推动,则询问用户
if (needSaveDraft ) {
showAskSaveDraftDialog();
}
} private void showAskSaveDraftDialog() {
// TODO Auto-generated method stub }

当前onSaveInstanceState函数调用完毕后,存储状态信息的outState对象中的数据就由系统进程代为保管,不论该应用进程是否被系统回收,这些数据都不会丢失。

假设savedInstanceState为空,说明这是一次全新的构造。反之则说明这是一次恢复性的构造。

界面组件能够利用该參数中的信息将界面状态恢复到系统回收前的状态。

区分是恢复性构造还是全新的狗仔,是开发中须要妥善处理的细节。假设是全新的构造,界面组件中须要分析调用发送的Intent对象,控制业务流程。而假设是恢复性构造,则须要将上次缓存的信息一一恢复。

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
needSaveDraft = savedInstanceState.getBoolean("NEED_SAVE_DRAFT" );
}
else {
// TODO 解析Intent对象传入的參数或者Action
// Intent intent = getIntent();
// intent.getBundleExtra("");
}
}

为了减少开发人员的负担。Android中的大部分的系统控件都实现了状态缓存的逻辑。在onSaveInstanceState函数调用前,界面组件会遍历整个控件树,将各个控件保存下来。等到onRestoreInstanceState函数被调用时在进行恢复。

假设系统内置的控件状态缓存逻辑不符合开发人员的需求,开发人员能够调用View.setSaveEnabled函数关闭相应控件对象的自己主动缓存。在onSaveInstanceState函数中自行管理控件的状态。

用于状态管理的onSaveInstanceState 和 onRestoreInstanceState并不属于主要的生命周期函数,可是状态管理的操作还是和组件的生命周期有必定的联系,开发人员相同须要妥善利用好这些函数,处理由于生命周期变更引起的变化。

注冊管理

界面组件在于用户交互的过程中有时候须要随着系统状态的变化及时的更新信息。比方地址信息。

界面组件能够通过监听相关的事件信息来捕获这些变化。假设所监听的事件的变化。仅当组件在前台状态时才须要生效(比方广播事件的监听。地理位置的变更等),则须要早onResume中注冊,在onPause中注销。

   LocationManager             mLocationManager;
LocationListener mLocationListener; @Override
protected void onResume() {
super.onResume();
mLocationManager.requestLocationUpdates(provider, minTime, minDistance, listener );
} @Override
protected void onPause() {
super.onPause();
mLocationManager.removeUpdates(mLocationListener );
}

线程管理

在应用开发中。网络通信、数据操作、复杂计算等都须要耗费大量的时间,因此应用通常须要採用多线程的设计模式,在后台线程中运行此类耗时的操作。

Android的组件生命周期,是一个典型的同步处理逻辑。

对于多线程架构没有提供良好的支持模型。这个须要开发人员依据自己的需求,充分利用好组件的生命周期,合理的安排线程的构造及销毁。

假设线程的生命周期和该组件的生命周期紧密联系,就须要在界面组件生命周期中管理该线程,一旦线程被界面组件构造出来,就须要在onDestory中明白终止该线程,回收其线程空间。否则,将导致线程资源泄漏。

可是仅在onDestory回收线程依旧不够完美,由于在资源紧张的情况下,系统会强行回收组件。此时组件的onDestory函数可能并没有调用。从而导致线程资源泄漏。

一个更好的线程管理方案,是将线程的句柄信息当做界面组件的状态信息缓存下来。

假设系统强行回收该对象组件,则须要在组件再次被构造时,依据缓存的线程句柄找到该线程。从而避免线程泄露。

static final String THREAD_WORKER_ID = “thread_id”;

Thread workerThread;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
long threadId = savedInstanceState.getLong(THREAD_WORKER_ID);
workerThread = findThreadById(threadId);
}
else {
// TODO 创建新的线程
}
} private Thread findThreadById( long id) {
// 完好依据线程id。找到该线程 的过程 http://bao231.iteye.com/blog/1917616?utm_source=tuicool return null ;
} @Override
protected void onDestroy() {
super.onDestroy();
if (workerThread != null) {
workerThread.interrupt();
workerThread = null ;
}
}

服务组件的生命周期

服务的使用方式可分为两种,各自是调用服务和绑定服务。这两种不同的使用方式下,生命周期稍微有不同。

但不论在何种使用模式下,组件的生命周期都是从onCreate中開始,至onDestory中结束。

由于服务组件开发中,能够选择在onCreate中做数据载入等初始化工作,而在onDestory中做数据销毁。线程终止等清理工作。

在绑定模式下。onBind函数被调用时,说明服务以及被前台界面组件绑定。服务组件应依据调用者传递的Intent对象。在该函数内载入资源,构建通信对象。等待绑定者的调用。当界面组件完毕相关操作时。需会解除与服务组件的绑定。此时,onUnBind函数会被调用,能够在该函数中做一些统计和资源清理工作。

被绑定服务组件的进程状态。与绑定该服务的界面组件密切相关。

假设绑定组件为前台界面组件。则改服务所处的进程即为前台进程。反之也相同。

Android系统不会轻易回收前台进程或者可视进程。所以出于绑定状态的组件通常也不会被强制停止。对于开发人员而言。绑定服务后一定不要忘记选择在合适的时机接触绑定。否则将使服务组件停留在前台或可视状态无法回收。从而浪费系统资源。

在调用模式,当服务组件运行onStartCommand函数时。服务所在的进程为前台进程,拥有最高的优先级。当onStartCommand函数运行完毕后。假设没有显示的调用stopSelf等相关函数来停止服务组件。那么该服务组件将会成为后台组件继续提供服务。直至调用stopSelf函数停止。或者等待系统强行回收。

onStartCommand函数中添加三个返回值和控制參数,用于指定后台服务组件的运行方式。当中最重要的返回值有三个:

START_STICKY —— 系统会对该服务组件负责究竟。在强行回收该组件后后,在资源宽裕的时候还会调用onStartCommand函数又一次启动该服务。直到调用stopSelf函数。对于开发人员而言,编写返回值为START_STRICKY,一定要在合适的时机调用stopSelf函数主动关闭服务,否则会无限期的消耗系统资源。

START_NOT_SRICKY —— 说明系统能够无条件的回收该组件,而无需关注服务是否完毕,也不须要负责服务的又一次启动。

START_REDELIVER_INTENT —— 则意味着须要保障该服务组件能够完整的处理完每个Intent对象。

触发器组件的生命周期:

触发器的生命周期是最短暂的。其整个生命周期就是构造触发器对象,然后运行onReceive函数。

对于运行完onReceive函数,系统会马上出发销毁触发器的组件对象,回收其占用的资源。

生命周期内,onReceive函数内部不能够处理耗时任务。

数据源组件的生命周期

理论上来说,数据源组件没有所谓的生命周期,因此数据源组件的状态不作为进程优先级的推断依据。所以系统在回收进程资源时,并不会将数据源的销毁事件告知开发人员。

但Android会在构造数据源组件时调用onCreate函数。开发人员能够在该函数中数据化数据源所需的数据库或者其它数据内容。

由此可知,在数据源组件中部署延迟写入等写优化策略是不合适。由于数据源组件可能会被系统静默回收,从而导致未持久化的写入数据丢失。所以在数据源组件的实现中,写优化策略应该交由上层调用去实现,或者下层数据存储者去处理。

一旦数据源组件构造出来,就会保持长期运行的状态直至其所在的进程被系统回收。所以不要再数据源组件中缓存过多的数据,以免占用内存空间。

观察者事件:

通常假设在onResume与onPause中,接收到观察者事件能够安全的运行兴许观察者事项。

尽量确保组件的观察者事件仅仅处理当前界面处于前台状态下的事物,而可视状态甚至后台状态下的事物,不能够依赖观察者事件来处理。

由于观察者事件并不能确保在组件生命之间可达。

观察者事件仅仅应该在组件可见的生命周期内运行监听,其余的数据更新须要依赖于组件的生命周期方法。

比方onStart,onStop,onResume,onPause等。过度依赖于观察者事件,将导致将必要的功能与观察者事件耦合。

观察者事件的add和remove须要成对出现。否则会引发内存泄露。

Android应用常规开发技巧——善用组件生命周期的更多相关文章

  1. android核心系列--1,组件生命周期

    一,进程模型及进程托管 1,一个APP应用是由一个或多个组件构成的,这些组件可以运行在一个进程中,也可以分别运行在多个进程中: 进程的构造和销毁是由系统全权负责的. 2,一个应用进程只有一个应用环境对 ...

  2. Android组件生命周期(二)

    引言 应用程序组件有一个生命周期——一开始Android实例化他们响应意图,直到结束实例被销毁.在这期间,他们有时候处于激活状态,有时候处于非激活状态:对于活动,对用户有时候可见,有时候不可见.组件生 ...

  3. Android组件生命周期(一)

    引言 应用程序组件有一个生命周期——一开始Android实例化他们响应意图,直到结束实例被销毁.在这期间,他们有时候处于激活状态,有时候处于非激活状态:对于活动,对用户有时候可见,有时候不可见.组件生 ...

  4. Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解

    前言 大家好,给大家带来Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解的概述,希望你们喜欢 Activity是什么 作为一个Activ ...

  5. vue- Vue-Cli脚手架工具安装 -创建项目-页面开发流程-组件生命周期- -03

    目录 Vue-Cli 项目环境搭建 与 python 基础环境对比 环境搭建 创建启动 vue 项目 命令创建项目(步骤小多) 启动 vue 项目(命令行方式) 启动 vue 项目(pycharm 方 ...

  6. Android SDK上手指南:Activity与生命周期

    Android SDK上手指南:Activity与生命周期 2013-12-26 15:26 核子可乐译 51CTO 字号:T | T Activity生命周期并不仅仅在用户运行应用程序之后才开始生效 ...

  7. [React] 多组件生命周期转换关系

    前段时间一直在基于React做开发,最近得空做一些总结,防止以后踩坑. 言归正传,React生命周期是React组件运行的基础,本文主要是归纳多组件平行.嵌套时,生命周期转换关系. 生命周期 Reac ...

  8. React.js 小书 Lesson20 - 更新阶段的组件生命周期

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson20 转载请注明出处,保留原文链接和作者信息. 从之前的章节我们了解到,组件的挂载指的是将组件 ...

  9. flex 组件重写 组件生命周期

    AS方式重写组件常规步骤 1.如果有必要,为组件创建所有基于标记(tag-based)的皮肤(skins) 2.创建ActionScript类文件 ⑴从一个基类扩展,比如UIComponent或者其他 ...

随机推荐

  1. EF Code First:实体映射,数据迁移,重构

    经过EF的<第一篇>,我们已经把数据访问层基本搭建起来了,但并没有涉及实体关系.实体关系对于一个数据库系统来说至关重要,而且EF的各个实体之间的联系,实体之间的协作,联合查询等也都依赖于这 ...

  2. Eclipse中高效的快捷键、调试及Junit

    Eclipse中高效的快捷键 当我知道了这些快捷键的用法之后,感觉真的非常兴奋,没想到Eclipse中还有这么多令人惊喜的功能,真的能够提高效率. 内容提示 Alt+/ 用于输入标准库或者keywor ...

  3. No unique bean of type [net.shougongfang.action.paymoney.AlipayPayMoneyReturnObj] is defined: Unsat

    0 你把@Service放到实现类上吧.这个问题好像不止一个人在问啦 2013年10月25日 10:34 shidan66  30  0 1 1 加入评论 00 1,@service放到实现上  2. ...

  4. iframe是否缓存页面探究

    近期手里有个项目须要用iframe来调用每天都会变化的页面,后来想到iframe会不会缓存页面呢.于是写了个demo论证了下,结果例如以下: iframe的src假设是静态页面,就有可能会缓存.由于静 ...

  5. 2015.04.27,外语,读书笔记-《Word Power Made Easy》 12 “如何奉承朋友” SESSION 35

    1.how to look 拉丁词根specto,to look的意思,是许多常见英文词语的来源,如spectacle(['spektәkl] n. 值得看的东西, 光景, 眼镜).spectator ...

  6. h5-登录

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  7. 互联网智能门锁,手机蓝牙APP成为首选

    随着互联网门锁在行业中的普及,大家越加关注到门锁的实施和维护成本.我们在互联网智能门锁的调研中发现,网关联网的智能门锁,使用时需要依赖房间内的宽带上网线路,而断线后客户反馈问题较多.据某家分散式公寓的 ...

  8. CDR中如何将对象在页面居中显示

    利用CorelDRAW在做设计排版时,如果想让对象在页面居中显示你会用什么方法?用鼠标拖?还是更准确的做法选择参照物对象,利用对齐与分布命令?或者还有更简单快速的方法,一起来看看吧! 最简单的方法(页 ...

  9. Day 07 数据类型的内置方法[列表,元组,字典,集合]

    数据类型的内置方法 一:列表类型[list] 1.用途:多个爱好,多个名字,多个装备等等 2.定义:[]内以逗号分隔多个元素,可以是任意类型的值 3.存在一个值/多个值:多个值 4.有序or无序:有序 ...

  10. Tensorflow学习笔记----基础(3)

    目录: 一.TensorFlow的系统架构 二.TensorFlow的设计理念 三.TensorFlow的运行流程 四.TensorFlow的编程模型:边.节点.图.设备.变量.变量初始化.内核 五. ...