1.引子

Activity就像是英文词汇本的Abandon,开篇就能碰到,关于Activity生命周期的博客教程非常多,侧面说明Activity非常重要,其中的Activity的生命周期又是重中之重,面试官非常喜欢拿这个作为考点,因为掌握Activity生命周期对提高应用的健壮性具有很大的帮助。因为只看教程不自己总结实践的话,对其理解总会差点意思,自己动手总结了印象才深刻。

2.Activity生命周期

一个Activity具有四个状态:

  1. 活动(active)或运行(running)状态:此时Activity位于栈顶,用户可以与之交互;
  2. 可见(visible)状态:该状态下Activity对用户可见,但失去了焦点,例如弹出一个对话框,对话框变成前景,原Activity变成背景板,进入可见状态,此时Activity还是活着的,一旦对话框消失,Activity立刻回到活动状态;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q97Zcg70-1586575759198)(./assets/可见.png)]
  3. 停止(stopped)或隐藏(hidden)状态:如果一个Activity完全被另一个Activity遮盖,则进入该状态,该状态下Activity仍保留着原先的状态信息,再次回到前台直接使用这些保留的信息,例如你从知乎的某个答案跳转到微博界面,此时知乎界面是停止状态,当你再次回到知乎界面时,因为保留了跳转时的状态,再次回到知乎界面还是你之前浏览的答案,注意,在停止状态下,如果系统资源紧张的话,则会销毁Activity,当然会把所有Activity保留的状态信息也清除了,这个时候再次回到知乎界面,只能是看一遍开屏广告再从首页开始吧;
  4. 销毁(destroyed)状态:系统终止Activity进程,在内存层面删除Activity。现在安卓手机的清理缓存功能其中一个功能是销毁堆栈中的Activity回收资源。当这个Activity再次向用户展示时,是重新创建后的实例了。就像她还是她,但已经不是你认识的她。

Activity生命周期其实是一个有限状态机,描述Activity对象如何在以上4种状态之间转换的,生命周期如图所示,图中矩形表示当Activity状态跳转时执行的回调方法。彩色椭圆矩形是Activity可以进入的主要状态,当然细心的同学会疑惑,彩色椭圆矩形里写的主要状态和4种状态对不上了,例如没见可见状态啊,个人认为彩色椭圆矩形指的是Activity动作状态,例如启动,运行,销毁,而上述4种状态是所处的静态状态,在周期图里用文字描述里,例如Activity进入可见状态,用The Activity is no longer visible来描述了。
这个图我们也许见过多次,跟词汇本老朋友Abandon一样,这个图非常重要,掌握了这个图,才能叫掌握Activity。

Activity生命周期有三种类型,其一是Activity的整个生命周期(entire lifetime),从onCreate()开始,到onDestroy()结束,也就是从出生到死亡,贯穿了Activity平庸的一生,Activity在onCreate()中完成所有全局状态设置,在onDestroy()中释放所有Activity资源;

其二是可见生命周期(visible lifetime),发生在onStart()onStop()之间,如图所示,为什么叫可见生命周期,这是因为周期开始onStart()和结束onStop()Activity处于可见状态,不过处于可见状态Activity还不能和用户进行交互,只能远观。我们发现其实可见生命周期大多数步骤还是和整个生命周期步骤是重合的,为何还单独提出来呢?因为周期的侧重点不同,在可见生命周期内可重点管理给用户显示所需的资源,例如UI的更改,而整个生命周期则可重点管理维护贯穿整个生命周期的资源。

最后是前台生命周期(foreground lifetime),发生在onResume()onPause之间在此期间,Activity处于运行状态,能够与用户进行交互。Activity频繁在onResumeonPause之间进行切换-例如设备锁屏和解锁,Activity被其他Activity覆盖和恢复等,因为频繁切换,所以应避免在这个生命周期内执行过多的代码,避免界面卡顿。

我们注意到,这三个生命周期发生的频度是逐渐增加的,就像时钟的三根针,整个生命周期是时针,步骤最长最多,发生的频度较低,可见生命周期是分针,步骤少一点,前台生命周期是秒针,步骤最少,发生的频度最高,开发者应根据这三类生命周期的特点,合理安排Activity所需资源的加载。

3.生命周期回调方法

3.1 生命周期回调方法介绍

我们来看一下生命周期里每一个环节的回调方法

  1. onCreate()
      Activity第一次创建时调用该方法,可在该方法中完成Activity初始化操作,例如创建视图,绑定按钮事件或其他全局性的资源加载。这是Activity整个生命周期的开始。

  2. onStart()
    当活动对用户可见时调用,是Activity可见生命周期的开始。

  3. onResume()
    当Activity开始与用户互动时调用。 此时Activity位于堆栈的顶部并处于运行状态。是Activity前台生命周期的开始。

  4. onPause()
      当Activity失去焦点或者即将隐藏/停止或销毁时调用,执行该方法期间Activity对用户仍可见,直到另一个Activity覆盖,一个比较相似的例子是游戏加载,在加载完新场景之前原场景一直对玩家显示,不过为了不能让玩家觉得是死机了,加载场景会切换成过场片段或者过场画面例如展示一下游戏技巧等给玩家知道游戏没有死机,同样道理,onPause()一样是执行过场的动作,官方推荐调用这个方法时让UI保持活动,同时方法内要执行的操作尽可能轻量化,别做太多的耗时操作。

  5. onStop()
    当Activity对用户完全不可见时调用,例如另一个Activity在栈顶,完全覆盖了当前的Activity,或者该Activity正在被销毁。该回调方法和onPause()方法的主要区别在于,如果启动的新Activity是一个对话框式的activity,那么,onPause()方法会得到执行,而onStop()方法并不会执行。

  6. onDestory()
      这个回调方法在Activity被销毁之前调用。

  7. onRestart()
    在Activity停止之后,再次启动之前调用,始终跟随onStart()

3.2 生命周期回调方法示例

我们在每个回调方法里添加log监控每个回调方法的运行情况,代码如下,然后再来执行各种操作看Activity生命周期。

package com.test.activitydemo;import androidx.appcompat.app.AppCompatActivity;import android.app.AlertDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {Button bclick;TextView tv;String TAG="Activity Life";//@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bclick=findViewById(R.id.button);tv=findViewById(R.id.textView);tv.setText("活动状态");Log.e(TAG, "start onCreate");bclick.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {tv.setText("可见状态");AlertDialog alertDialog1 = new AlertDialog.Builder(MainActivity.this).setTitle("弹框")//标题.setMessage("弹框变成前景,验证onPaus是否执行")//内容.setIcon(R.mipmap.ic_launcher)//图标.create();alertDialog1.show();}});}// 当活动对用户可见时调用,Activity可见生命周期的开始。@Overrideprotected void onStart(){super.onStart();Log.e(TAG, "start onStart");}// 在Activity停止之后,再次启动之前调用,其后是onStart(),也就是可见生命周期开始.@Overrideprotected void onRestart(){super.onRestart();Log.e(TAG, "start onRestart");}// 前台生命周期开始@Overrideprotected void onResume(){super.onResume();Log.e(TAG, "start onResume");}// 前台生命周期结束前调用@Overrideprotected void onPause(){super.onPause();Log.e(TAG, "start onPause");}// 可见生命周期结束即将结束前调用@Overrideprotected void onStop(){super.onStop();Log.e(TAG, "start onStop");}// 销毁前调用.@Overrideprotected void onDestroy(){super.onDestroy();Log.e(TAG, "start onDestroy");}
}
  1. 首先是启动demo,我们看到Activity逐一调用了onCreate(),onStart(),onResume(),然后进入Activity界面,对应Activity整个生命周期的前三个回调函数;
  2. 然后我们点击按钮,在Activity上弹个框,看看是否回调onPause(),结束前台生命周期。我们看到,有弹框在Activity之上,但并没有回调onPause(),也就是说,Activity没有结束前台生命周期,当前Activity还是在栈顶,不是说有弹框部分覆盖Activity,Activity失去焦点后结束前台生命周期吗,这是怎么回事?这是因为创建的AlertDialog对话框有一个context类型的参数,该参数表示AlertDialog是在Activity的上下文创建的,表示弹出的AlertDialog仍属于当前Activity,Activity没退居幕后,所以不会执行onPause().那怎样的弹框才能进入onPause()呢?只能是伪装成弹框的Activity了。为什么需要是弹框式Activity,普通的Activity是否可行?普通的Activity完全覆盖了当前的Activity,当前Activity不可见了,弹框式Activity没有完全覆盖当前Activity,Activity结束前台生命周期,但仍然可见。

    将普通Activity变成弹框式,只需要修改主题(Theme)成弹框主题即可,弹框主题在style.xml里设置,代码如下
<style name="dialogstyle"><!--设置dialog的背景--><item name="android:windowBackground">@android:color/transparent</item><!--设置Dialog的windowFrame框为无--><item name="android:windowFrame">@null</item><!--设置无标题--><item name="android:windowNoTitle">true</item><!--是否浮现在activity之上--><item name="android:windowIsFloating">true</item><!--是否半透明--><item name="android:windowIsTranslucent">true</item><!--设置窗口内容不覆盖--><item name="android:windowContentOverlay">@null</item><!--设置动画,在这里使用让它继承系统的Animation.Dialog--><item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item><!--背景是否模糊显示--><item name="android:backgroundDimEnabled">true</item>
</style>

然后在AndroidManifest.xml里修改Activity主题

      <activityandroid:name=".AlertDialogActiviy"android:theme="@style/dialogstyle" />

最后在代码中实现跳转

Intent intent = new Intent(MainActivity.this, AlertDialogActiviy.class);startActivity(intent);

这样我们打开Activity弹框时,原Activity仍可见,我们看logcat,可看到已经调用onPause(),表示结束了前台生命周期。我们点导航栏的返回键,回到原Activity界面,则回调onResume方法,重新进入前台生命周期。


3. 现在来看下可见生命周期的示例。这个比较简单,只要调用另外一个Activity或者回调桌面(桌面其实也是一个Activity)即可,只要让我们的Activity不可见就行。为了方便(偷懒),我用回到桌面来验证,验证的logcat截图如下,可以看到,首先回调onPause(),随着Activity消失,桌面完全显示,最后回调onStop(),正式结束可见生命周期。

然后我们再从桌面回到Activity,logcat截图如下,首先回调onRestart(),宣布复活,然后是onStart(),进入可见生命周期,最后调用onResume(),进入前台生命周期。

4. 最后看销毁Activity的回调方法,操作方法很简单,杀掉Activity即可调用,不再赘述。

Activity生命周期的学习和验证相关推荐

  1. 安卓学习笔记06:Activity生命周期与启动模式

    文章目录 零.学习目标 一.Activity生命周期 1.了解Activity生命周期 2.Activity生命周期简化图 (1)Activity存在与否 (2)Activity可见与否 (3)Act ...

  2. Activity生命周期学习总结2

    1:上期对于Activity的生命周期的理解不是很到位,这次再来展示下Activity在横竖屏切换,按钮点击下运行流程是什么怎么样的. 2:接着上次的来讲 (1)直接运行后,先是创建到可见,在到可用 ...

  3. Android 插件化原理解析——Activity生命周期管理

    之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在A ...

  4. Android全面解析之Activity生命周期

    前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Activity生命周期的文章,网络上真的很多,有很多的博客也都讲得相当不错,可见Activity的重要性是非常高的.事实上,我猜测每个android开发 ...

  5. Activity与调用线(三):Activity生命周期源码解析

    前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Activity生命周期的文章,网络上真的很多,有很多的博客也都讲得相当不错,可见Activity的重要性是非常高的.事实上,我猜测每个android开发 ...

  6. Activity生命周期管理

    之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在A ...

  7. 基础总结篇之一:Activity生命周期

    子曰:溫故而知新,可以為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就完全掌握,那基本不大可能,所以我们需要经常回过头再仔细研读几遍,以领悟到作者的思想精 ...

  8. activity 生命周期_死磕Android_App 启动过程(含 Activity 启动过程)

    1. 前言 Activity是日常开发中最常用的组件,系统给我们做了很多很多的封装,让我们平时用起来特别简单,很顺畅.但是你有没有想过,系统内部是如何启动一个Activity的呢?Activity对象 ...

  9. Android的Activity生命周期模拟程序及解析

    当Activity处于Android应用中运行时,它的活动状态由Android以Activity栈的形式管理.当前活动的Activity位于栈顶.随着不同应用的运行,每个Activity都有可能从活动 ...

最新文章

  1. 原创 | 从ULMFiT、Transformer、BERT等经典模型看NLP 发展趋势
  2. python实现多进程同时计算_python多进程实现CPU100%使用
  3. 沉思录---Windows Phone软件开发Beta版回首
  4. 数组delete[] 出错 可能是堆被破坏
  5. sde表空间无法导入数据和编辑
  6. java解析sql查询字段_sql解析json格式字段 如何获取json中某个字段的值?
  7. linux安装多个mysql数据库_linux下多个mysql5.7.19(tar.gz)安装图文教程
  8. hades武器第四形态解锁_凯多的第四个技能预告——冰冻!
  9. c++ 连接两个字符串实现代码 实现类似strcat功能(转)
  10. 解决 VUE: 本地运行和服务器上运行样式不一致,run、build 运行时样式有出入
  11. jquery动画效果总结
  12. 搭建接口自动化测试框架详细过程
  13. 几本开关电源书籍 pdf格式 (来源中国电子开发网)
  14. 西电计算机学院专硕复试成绩,2018年西安电子科技大学硕士研究生招生统考考生拟录取名单公示...
  15. access有效性规则不为空值_Access 有效性规则/验证规则
  16. JDE910笔记2--OMW项目建立及简单使用[转]
  17. win8: html5+css3+js
  18. 技术人生:真的要注意身体了,坚持锻炼
  19. iOS编译cURL库并链接darwinssl,zlib,c-ares库操作步骤
  20. 区块链技术能否给跨境贸易带来新的机遇?

热门文章

  1. boost::hana::cycle用法的测试程序
  2. boost::date_time模块测试时间分辨率特征
  3. boost::pointer_traits用法实例
  4. DCMTK:类DcmUniqueIdentifier的测试程序
  5. QML和C ++之间的数据类型转换
  6. OpenGL Static Texture静态纹理的实例
  7. OpenGL设置透视投影并渲染旋转的立方体
  8. C++binary exponent二元指数算法的实现(附完整源码)
  9. C语言数组的深入理解
  10. QT的QScriptEngineAgent类的使用