2019独角兽企业重金招聘Python工程师标准>>>

Activity是Android程序的4大组件之一,是Android程序的表示层。程序的每一个显示屏幕就是一个Activity,它上面可以显示一些控件也可以监听并处理用户的事件做出响应,Activity之间通过Intent进行通信。

一、Activity 的生命周期:

为了理解生命周期,先说一下任务:任务其实就是“应用程序”,它是由一个或多个Activity组成的共同完成一个完整的用户体验。

比如我们打开QQ首先进入联系人列表界面,这个界面就是一个Activity:

点击“添加好友”便进入到搜索的Activity:

点击一条搜索结果便进入到了名片的Activity:

一个任务的Activity是由栈的形式存储的,栈底的是启动整个任务的Activity,栈顶的是当前运行的用户可以交互的Activity,当一个activity 启动另外一个的时候,新的activity 就被压入栈,并成为当前运行的activity。而前一个activity 仍保持在栈之中。当用户按下BACK 键的时候,当前activity 出栈,而前一个恢复为当前运行的activity。栈中的Activity 永远不会重排,只会压入或弹出。

任务中的所有Activity 是作为一个整体进行移动的。整个的任务(即Activity 栈)可以移到前台,或退至后台。举个例子说,比如当前任务在栈中存有四个Activity──三个在当前Activity 之下。当用户按下HOME 键的时候,回到了系统界面,然后选择了一个新的应用程序(也就是一个新任务)。则当前任务转入后台,而新任务的根Activity 显示出来。然后,用户再次回到了系统界面选择了前一个应用程序(上一个任务)。于是那个任务,带着它栈中所有的四个Activity,再一次的到了前台。当用户按下BACK 键的时候,屏幕不会回到用户刚才离开的任务。取而代之,当前任务的栈中最上面的Activity 被弹出,倒数第二个Activity 显示了出来。

Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。为了解决这个问题, Android 引入了一个新的机制-- 生命周期(Life Cycle)。Android 应用程序的生命周期是由Android 框架进行管理,而不是由应用程序控制。通常,每一个应用程序(入口一般会是一个Activity 的onCreate 方法),都会产生一个进程(Process)。当系统内存即将不足的时候,会依照优先级自动进行进程(process)的回收。不管是使用者或开发者, 都无法确定的应用程序何时会被回收。所以为了防止数据丢失和其他问题,了解生命周期很重要。

1、四种状态:

1.活动(Active/Running)状态:
当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于运行状态,同一个时刻只会有一个Activity 处于活动(Active)或运行(Running)状态。
2.暂停(Paused)状态:
当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出窗口时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但是当系统内存极小时可以被系统杀掉。
3.停止(Stopped)状态:
完全被另一个Activity遮挡时处于停止状态,它仍然保留着所有的状态和成员信息。只是对用户不可见,当其他地方需要内存时它往往被系统杀掉。
4.非活动(Dead)状态:
Activity 尚未被启动、已经被手动终止,或已经被系统回收时处于非活动的状态,要手动终止Activity,可以在程序中调用"finish"方法。如果是(按根据内存不足时的回收规则)被系统回收,可能是因为内存不足了。

内存不足时,Dalvak 虚拟机会根据其内存回收规则来回收内存:

1.先回收与其他Activity 或Service/Intent Receiver 无关的进程(即优先回收独立的Activity)因此建议我们的一些(耗时)后台操作,最好是作成Service的形式。
2.不可见(处于Stopped状态的)Activity。
3.Service进程(除非真的没有内存可用时会被销毁)。
4.非活动的可见的(Paused状态的)Activity。
5.当前正在运行(Active/Running状态的)Activity。

2、七个重要方法,当Activity从一种状态进入另一状态时系统会自动调用下面相应的方法来通知用户这种变化:

1.onCreate(Bundle savedInstanceState):
当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法通常用于初始化设置,为Activity设置所要使用的布局文件,为按钮绑定监听器等静态的设置操作。
2.onStart():
当Activity可见未获得用户焦点不能交互时系统会调用。
3.onRestart():
当Activity已经停止然后重新被启动时系统会调用。
4.onResume():
当Activity可见且获得用户焦点能交互时系统会调用。
5.onPause():
当系统启动另外一个新的Activity时,在新Activity启动之前被系统调用保存现有的Activity中的持久数据、停止动画等,这个实现方法必须非常快。当由系统而不是用户自己出于回收内存时,关闭了Activity 之后。用户会期望当他再次回到这个Activity 的时候,它仍保持着上次离开时的样子。此时用到了onSaveInstanceState(),方法onSaveInstanceState()用来保存Activity被杀之前的状态,在onPause()之前被触发,当系统为了节省内存销毁了Activity(用户本不想销毁)时就需要重写这个方法了,当此Activity再次被实例化时会通过onCreate(Bundle savedInstanceState)将已经保存的临时状态数据传入。因为onSaveInstanceState()方法不总是被调用,因为有些场景是不需要保存状态数据的。 比如用户按下BACK键退出activity时, 用户显然想要关闭这个activity,此时是没有必要保存数据以供下次恢复的,也就是onSaveInstanceState()方法不会被调用。onSaveInstanceState()方法触发条件为(按下HOME键,按下电源按键关闭屏幕,横竖屏切换情况下),应该仅重写onSaveInstanceState()来记录Activity的临时状态,而不是持久的数据。应该使用onPause()来存储持久数据。
6.onStop():
当Activity被新的Activity完全覆盖不可见时被系统调用。
7.onDestroy():
当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程等。

3、三个嵌套循环

1.Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束
2.Activity的可视生命周期:从调用onStart()到相应的调用onStop()在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop() 中注销。
3.Activity的前台生命周期:从调用onResume()到相应的调用onPause()。

举例说明:
有3个Acitivity,分别用One,Two(透明的),Three表示,One是应用启动时的主Activity;

启动第一个界面Activity One时,它的次序是:
onCreate (ONE) - onStart (ONE) - onResume(ONE)
点"打开透明Activity"按钮时,这时走的次序是:
onPause(ONE) - onCreate(TWO) - onStart(TWO) - onResume(TWO)
再点back回到第一个界面,Two会被杀这时走的次序是:
onPause(TWO) - onActivityResult(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO)
点"打开全屏Activity"按钮时,这时走的次序是:
onPause(ONE) - onCreate(Three) - onStart(Three) - onResume(Three) - onStop(ONE)
再点back回到第一个界面,Three会被杀这时走的次序是:
onPause(Three) - onActivityResult(ONE) - onRestart(ONE) - onStart(ONE)- onResume(ONE) - onStop(Three) - onDestroy(Three)
再点back退出应用时,它的次序是:
onPause(ONE) - onStop(ONE) - onDestroy(ONE)

二、代码示例:

新建一个测试项目,并在MainActivity写以下代码:

 1 /** Called when the activity is first created. */
 2     @Override
 3     public void onCreate(Bundle savedInstanceState) {
 4         super.onCreate(savedInstanceState);
 5         setContentView(R.layout.main);
 6         Toast.makeText(this, "onCreate(Bundle savedInstanceState)方法被调用了。", Toast.LENGTH_SHORT).show();
 7     }
 8
 9     @Override
10     public void onStart(){
11         super.onStart();
12         Toast.makeText(this, "onStart()方法被调用了。", Toast.LENGTH_SHORT).show();
13     }
14
15     @Override
16     public void onRestoreInstanceState(Bundle savedInstanceState){
17         super.onRestoreInstanceState(savedInstanceState);
18         Toast.makeText(this, "onRestoreInstanceState(Bundle savedInstanceState)方法被调用了。", Toast.LENGTH_SHORT).show();
19     }
20
21     @Override
22     public void onRestart(){
23         super.onRestart();
24         Toast.makeText(this, "onRestart()方法被调用了。", Toast.LENGTH_SHORT).show();
25     }
26
27     @Override
28     public void onSaveInstanceState(Bundle savedInstanceState){
29         super.onSaveInstanceState(savedInstanceState);
30         Toast.makeText(this, "onSaveInstanceState(Bundle savedInstanceState)方法被调用了。", Toast.LENGTH_SHORT).show();
31     }
32
33     @Override
34     public void onPause(){
35         super.onPause();
36         Toast.makeText(this, "onPause()方法被调用了。", Toast.LENGTH_SHORT).show();
37     }
38
39     @Override
40     public void onResume(){
41         super.onResume();
42         Toast.makeText(this, "onResume方法被调用了。", Toast.LENGTH_SHORT).show();
43     }
44
45     @Override
46     public void onStop(){
47         super.onStop();
48         Toast.makeText(this, "onStop()方法被调用了。", Toast.LENGTH_SHORT).show();
49     }
50
51     @Override
52     public void onDestroy(){
53         super.onDestroy();
54         Toast.makeText(this, "onDestroy()方法被调用了。", Toast.LENGTH_SHORT).show();
55     }
56
57     @Override
58     public void onConfigurationChanged(Configuration newConfig){
59         super.onConfigurationChanged(newConfig);
60         Toast.makeText(this, "onConfigurationChanged()方法被调用了。", Toast.LENGTH_SHORT).show();
61     }

运行后在模拟器上观察方法的调用情况。

三、横竖屏切换时候Activity的生命周期:

1.默认设置切换时的生命周期:

运行刚才新建的测试项目,Toast消息的提示调用顺序是:

“onCreate”->"onStart"->"onResume"

按crtl+f12切换模拟器为横屏时,Toast消息的提示调用顺序是:

“onSaveInstanceState”->"onPause"->"onStop"->"onDestroy"->"onCreate"->"onStart"->"onRestoreInstanceState"->"onResume"

再次按按crtl+f12切换模拟器为竖屏时,发现Toast消息显示了2次相同的调用顺序:

“onSaveInstanceState”->"onPause"->"onStop"->"onDestroy"->"onCreate"->"onStart"->"onRestoreInstanceState"->"onResume"->
"onSaveInstanceState"->"onPause"->"onStop"->"onDestroy"->"onCreate"->"onStart"->"onRestoreInstanceState"->"onResume"

2.修改AndroidManifest.xml,在该Activity添加android:configChanges="orientation":

1 <activity android:name=".MainActivityLife"
2                   android:label="@string/app_name" android:configChanges="orientation">
3             <intent-filter>
4                 <action android:name="android.intent.action.MAIN" />
5                 <category android:name="android.intent.category.LAUNCHER" />
6             </intent-filter>
7 </activity>

重新生成并运行项目,然后按crtl+f12切换模拟器为横屏时,Toast消息的提示调用顺序是:

“onSaveInstanceState”->"onPause"->"onStop"->"onDestroy"->"onCreate"->"onStart"->"onRestoreInstanceState"->"onResume"

再次按按crtl+f12切换模拟器为竖屏时,Toast消息的提示多了一个"onConfigurationChanged":

“onSaveInstanceState”->"onPause"->"onStop"->"onDestroy"->"onCreate"->"onStart"->"onRestoreInstanceState"->"onResume"->"onConfigurationChanged"

3.修改AndroidManifest.xml,把刚才添加的android:configChanges="orientation"改为android:configChanges="keyboardHidden|orientation":

1 <activity android:name=".MainActivityLife"
2                   android:label="@string/app_name" android:configChanges="keyboardHidden|orientation">
3             <intent-filter>
4                 <action android:name="android.intent.action.MAIN" />
5                 <category android:name="android.intent.category.LAUNCHER" />
6             </intent-filter>
7 </activity>

重新生成并运行项目,然后按crtl+f12切换模拟器为横屏时,Toast消息只提示了"onConfigurationChanged":

"onConfigurationChanged"

再次按按crtl+f12切换模拟器为竖屏时,Toast消息提示了2次"onConfigurationChanged":

"onConfigurationChanged"->"onConfigurationChanged"

4.总结:

不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。

设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次,且在竖屏时执行了一次"onConfigurationChanged"。

设置Activity的android:configChanges="keyboardHidden|orientation"时,切屏不会重新调用各个生命周期,只会执行"onConfigurationChanged"。

转载于:https://my.oschina.net/secyaher/blog/274445

Android开发入门教程--3.Activity入门指南相关推荐

  1. 视频教程-快速入门Android开发 视频 教程 android studio-Android

    快速入门Android开发 视频 教程 android studio 任苹蜻,爱学啊创始人 & CEO,曾就职于某二车手公司担任Android工程师后离职创办爱学啊,我们的宗旨是:人生苦短,我 ...

  2. Android开发书籍推荐:从入门到精通系列学习路线书籍介绍

    很多时候我们都会不断收到新手的提问"Android开发的经典入门教材和学习路线?"."Android 开发入门教程有哪些推荐?"等类似的问题,我们不断重复回答这 ...

  3. Flowable 快速入门教程:Flowable 入门开发案例,结合流程设计器详细讲解

    Flowable 快速入门教程:Flowable 入门开发案例,结合流程设计器详细讲解 前言 流程设计器集成 整体流程图 流程节点说明 第一审核人节点:实际设置审核人 配置信息 说明 第二审核人:参数 ...

  4. Android开发原创教程

    qianqianlianmeng Android开发原创教程 活动帖子: http://www.apkbus.com/android-17709-1-1.html 安卓巴士ID 参赛帖子名称 巴士评分 ...

  5. Android开发简易教程

    Android开发简易教程 Android 开发因为涉及到代码编辑.UI 布局.打包等工序,有一款好用的IDE非常重要.Google 最早提供了基于 Eclipse 的 ADT 作为开发工具,后来在2 ...

  6. Python零基础入门教程( 快速入门)

    前言 学无止境,无止境学. 今天要给大家分享的是<Python零基础入门教程01 快速入门>,这是一个系列的教程,从零基础到项目实战.在本教程中,我会给大家介绍Python入门的一些基础知 ...

  7. android开发出现No Launcher activity found!解决方案

    android开发出现No Launcher activity found!解决方案 参考文章: (1)android开发出现No Launcher activity found!解决方案 (2)ht ...

  8. Android开发——异步任务中Activity销毁时的问题

    0.  前言 在Android开发中经常会发生Activity的销毁重建,比如用户长时间接听一个电话后回到APP.在Android开发--Fragment知识整理(二)中我们提到了使用Fragment ...

  9. # android开发:4-1、Activity启动方式、生命周期、不同activity的数据传递

    4.Activity活动简介 什么是Activity: 如何创建Activity: Activity启动方式: Activity的生命周期: 不同Activity之间数据的传递: 什么是Activit ...

  10. [入门教程](python numpy入门)

    [入门教程](python numpy入门) NumPy NumPy是一个开源的Python科学计算基础库,包含 •一个强大的N维数组对象ndarray •广播功能函数 •整合C/C++/Fortra ...

最新文章

  1. Python Re 模块超全解读!详细
  2. 二分查找的基本原理及实现
  3. informix 访问mysql_informix用户权限的介绍及查看方法
  4. Redis _面试经典
  5. PyCharm注册码
  6. python测试驱动开发百度云_【有书共读】《Python测试驱动开发》读书笔记01
  7. 如何把竖排的数据变为横排_读懂微信改版背后的焦虑,企业新媒体营销该如何自救?...
  8. SSM项目实战之八:静态资源文件的整合
  9. termios结构体详解
  10. IDE工具(17) eclipse创建ftl文件具体步骤
  11. greenDao的使用教程
  12. 华为路由器基本使用命令
  13. 入侵服务器修改手游,如何入侵手游服务器数据库
  14. 开关电源学习笔记9 --- SPEIC变换器
  15. matlab 三维 作图 坐标轴_matlab三维画图
  16. 如何在BIOS中开启虚拟化技术
  17. c#中https通讯如何添加证书
  18. 建筑力学与结构【3】
  19. 利用ps导出svg(主要用于上传自定义图标到iconfont)
  20. 计算机网络网络层之路由算法2链路状态路由算法

热门文章

  1. 单片机的C语言中位操作用法
  2. keydown - keypress - keyup 用法和区别
  3. 网络助手之NABCD
  4. Javascript (history,location)对象
  5. Linux常用shell脚本
  6. iOS底层探索之类的加载(四):类的关联对象AssociatedObject
  7. iOS 数组模型排序
  8. PhpStorm连接docker容器内的php XDebug进行断点调试
  9. ORACLE关联查询
  10. enetics v1.5.0 绿色版