文档章节

Activity生命周期

QGlaunch
 QGlaunch
发布于 2015/06/17 17:41
字数 2179
阅读 136
收藏 13
点赞 1
评论 0

Android官方文档和其他不少资料都对Activity生命周期进行了详细介绍,在结合资料和项目开发过程中遇到的问题,本文将对Activity生命周期进行一次总结。

Activity是由Activity栈进管理,当来到一个新的Activity后,此Activity将被加入到Activity栈顶,之前的Activity位于此Activity底部。Acitivity一般意义上有四种状态:

1.当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态

2.当Activity失去了焦点但仍然对用于可见(如栈顶的Activity是透明的或者栈顶Activity并不是铺满整个手机屏幕),此时处于暂停状态

3.当Activity被其他Activity完全遮挡,此时此Activity对用户不可见,此时处于停止状态

4.当Activity由于人为或系统原因(如低内存等)被销毁,此时处于销毁状态;

在每个不同的状态阶段,Adnroid系统对Activity内相应的方法进行了回调。因此,我们在程序中写Activity时,一般都是继承Activity类并重写相应的回调方法。

先贴一张来自官方文档(http://developer.android.com/reference/android/app/Activity.html)的图,相信大家都看到过。

 

图中详细给出了Activity整个生命周期的过程,以及在不同的状态期间相应的回调方法。

图中需要注意一下几点:

1.Activity实例是由系统自动创建,并在不同的状态期间回调相应的方法。一个最简单的完整的Activity生命周期会按照如下顺序回调:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。称之为entire lifetime。

2.当执行onStart回调方法时,Activity开始被用户所见(也就是说,onCreate时用户是看不到此Activity的,那用户看到的是哪个?当然是此Activity之前的那个Activity),一直到onStop之前,此阶段Activity都是被用户可见,称之为visible lifetime。

3.当执行到onResume回调方法时,Activity可以响应用户交互,一直到onPause方法之前,此阶段Activity称之为foreground lifetime。

在实际应用场景中,假设A Activity位于栈顶,此时用户操作,从A Activity跳转到B Activity。那么对AB来说,具体会回调哪些生命周期中的方法呢?回调方法的具体回调顺序又是怎么样的呢?

开始时,A被实例化,执行的回调有A:onCreate -> A:onStart -> A:onResume。

当用户点击A中按钮来到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。

此时如果点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。

至此,Activity栈中只有A。在Android中,有两个按键在影响Activity生命周期这块需要格外区分下,即Back键和Home键。我们先直接看下实验结果:

此时如果按下Back键,系统返回到桌面,并依次执行A:onPause -> A:onStop -> A:onDestroy。

此时如果按下Home键(非长按),系统返回到桌面,并依次执行A:onPause -> A:onStop。由此可见,Back键和Home键主要区别在于是否会执行onDestroy。

此时如果长按Home键,不同手机可能弹出不同内容,Activity生命周期未发生变化(由小米2s测的,不知道其他手机是否会对Activity生命周期有影响)。

由于Android本身的特性,使得现在不少应用都没有直接退出应用程序的功能,按照一般的逻辑,当Activity栈中有且只有一个Activity时,当按下Back键此Activity会执行onDestroy,那么下次点击此应用程图标将从重新启动,因此,当前不少应用程序都是采取如Home键的效果,当点击了Back键,系统返回到桌面,然后点击应用程序图标,直接回到之前的Activity界面,这种效果是怎么实现的呢?

通过重写按下Back键的回调函数,转成Home键的效果即可。

@Overridepublic void onBackPressed() {
    Intent home = new Intent(Intent.ACTION_MAIN);
    home.addCategory(Intent.CATEGORY_HOME);
    startActivity(home);
}

当然,此种方式通过Home键效果强行影响到Back键对Activity生命周期的影响。注意,此方法只是针对按Back键需要退回到桌面时的Activity且达到Home效果才重写。

或者,为达到此类效果,Activity实际上提供了直接的方法。

1 activity.moveTaskToBack(true);

moveTaskToBack()此方法直接将当前Activity所在的Task移到后台,同时保留activity顺序和状态。

 

在之前的项目开发过程中,当时遇到一个很奇怪的问题:手机上的“开发者选项”中有一个“不保留活动”的设置,当开启此设置,手机上的设置提示是“用户离开后即销毁每个活动”,开启后,对于其他的应用程序是从A Acticity到B Activity,然后Back键回到A,此时,其他应用程序只是先白屏(有可能黑屏等,取决于主题设置)一下,然后A开始可见,但是我的应用程序中出现的一个结果却是直接返回到了桌面。一开始百思不得其解。最后终于定位出问题。首先,我们需要明确开启此设置项后对Activity生命周期的影响。开启此设置项后,当A到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy。是的,A在系统原本的生命周期回调中增加了onDestroy。此即“用户离开后即销毁每个活动”的含义。但此时需要注意的是,只要没有认为的调用A的finish()方法,虽然A执行了onDestroy,但Activity栈中依然保留有A,此时B处于栈顶。那么在B中按Back键回到A时,将依次执行:B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。没错,A从onCreate开始执行了。此处也就解释了为什么A可能会出现白屏(或黑屏等)一下的原因了。

那么为什么我的应用程序会跟其他应用程序出现不一样呢?最后定为出问题在于当时我的应用程序中为了做到完全退出应用程序效果,专门使用了一个Activity栈去维护Activity(当时是借鉴了网上的此类实现方案,现在想想,实在没必要,且不说Android本身特性决定了没必要通过如此方法去达到退出效果,仅仅是此方法本身也存在很大的问题,现在在网上依然能见到有不少文章说到应用程序退出可以使用此方法,哎。。),在onCreate中入栈,onDestroy出栈,调用了如下方法

1 // 结束Activity&从堆栈中移除2 AppManager.getAppManager().finishActivity(this);

其中,AppManager中finishActivity函数具体定义是:

复制代码

 1 /** 2  * 结束指定的Activity 3  */ 4 public void finishActivity(Activity activity) { 5     if (activity != null) { 6         activityStack.remove(activity); 7         activity.finish(); 8         activity = null; 9     }10 }

复制代码

至此,相信大家应该看出问题的所在了吧。

没错,问题在于执行了activity的finish()方法!! activity的finish()方法至少有两个层面含义,1.将此Activity从Activity栈中移除,2.调用了此Activity的onDestroy方法。对于不开启“不保留活动”的设置项,实际上也没什么影响,但是一旦开启此设置,问题显露无疑。开启此此设置后,正常情况下离开A,即使执行了A的onDestroy,Activity栈中还是有A的,但是我这样写后,finish()方法一执行,Activity栈中就没有A了,因此,当点击Back键时,Activity栈中已经没有此应用的任何Activity了,直接来到了手机桌面。

可能,有些人会说,我就是要通过此种方法想去完全退出应用程序,同时希望自己的Activity栈和系统中Activity栈保持一致,怎么办呢?

在此,可以通过如下改写去实现:

 

复制代码

/*** 结束指定的Activity */public void finishActivity(Activity activity) {    if (activity != null) {    // 为与系统Activity栈保持一致,且考虑到手机设置项里的"不保留活动"选项引起的Activity生命周期调用onDestroy()方法所带来的问题,此处需要作出如下修正
    if(activity.isFinishing()){
        activityStack.remove(activity);        //activity.finish();
        activity = null;
    }
    }
}

复制代码

 

以此谨记!

-------------------------------------------------

此外,对于不同的启动模式或Intent Flags或操作行为(如横竖屏切换)等有可能会影响到Activity生命周期,此类问题将放在后续相关文章中进行总结。


本文转载自:http://www.cnblogs.com/lwbqqyumidi/p/3769113.html

共有 人打赏支持
QGlaunch
粉丝 4
博文 59
码字总数 11843
作品 0
朝阳

暂无相关文章

Day 17 vim简介与一般模式介绍

vim简介 vi和Vim的最大区别就是编辑一个文件时vi不会显示颜色,而Vim会显示颜色。显示颜色更便于用户编辑,凄然功能没有太大的区别 使用 yum install -y vim-enhanced 安装 vim的三种常用模式...

杉下 ⋅ 53分钟前 ⋅ 0

【每天一个JQuery特效】根据可见状态确定是否显示或隐藏元素(3)

效果图示: 主要代码: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>根据可见状态确定 是否显示或隐藏元素</title><script src="js/jquery-3.3.1.min.js" ty......

Rhymo-Wu ⋅ 今天 ⋅ 0

OSChina 周四乱弹 —— 初中我身体就已经垮了,不知道为什么

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @加油东溪少年 :下完这场雨 后弦 《下完这场雨》- 后弦 手机党少年们想听歌,请使劲儿戳(这里) @马丁的代码 :买了日本 日本果然赢了 翻了...

小小编辑 ⋅ 今天 ⋅ 12

浅谈springboot Web模式下的线程安全问题

我们在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,所以并不存在线程安全问题。 由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,...

算法之名 ⋅ 今天 ⋅ 0

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部