Android 学习之活动的生命周期
•返回栈
Android 中的活动是可以叠层的;
我们每启动一个新的活动,就会覆盖在原活动之上;
然后点击 Back 键会销毁最上面的活动,下面一个活动就会重新显示出来;
其实 Android 是使用任务(Task)来管理活动的;
一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack);
栈是一种后进先出的数据结构,在默认情况下,每当我们启动了一个新的活动,它会在返回栈中入栈;
并处于栈顶的位置,而每当我们按下 Back 键或者调用 finish() 方法去销毁一个活动时;
处于栈顶的活动会出栈,这时,前一个入栈的活动就会重新处于栈顶位置;
系统总是会显示栈顶的活动给用户。
•活动的状态
- 运行状态
- 当一个活动位于返回栈的栈顶时,这时活动就处于运行状态
- 系统最不愿意回收的就是处于运行状态的活动,因为这会带来非常差的用户体验
暂停状态
- 当一个活动不再处于栈顶位置,但仍然可见时,这时活动就进入了暂停状态
- 比如对话框形式的活动只会占用屏幕中间的部分区域,你还可以看到后边的界面
- 这时,后面的活动就处于暂停状态
停止状态
- 当一个活动不在处于栈顶位置,并且完全处于不可见的时候,就进入了停止状态
- 系统仍然会为这种活动保存相应的状态和成员变量,但是这并不是完全可靠的
- 当其他地方需要内存时,处于停止状态的活动有可能会被系统回收
销毁状态
- 当一个活动从返回栈中移除后就变成了销毁状态
- 系统倾向于回收处于这种状态的活动,从而保证手机内存充足
•活动的生存期
Activity 类中定义了七个回调方法,覆盖了活动生命周期的每一个环节;
onCreate()
- 每个活动中都重写这个方法,他会在活动第一次被创建的时候调用
- 你应该在这个方法中完成活动的初始化操作,比如加载布局、绑定事件等
onStart()
- 这个方法在活动由不可见变为可见的时候调用
onResume()
- 这个方法在活动准备好和用户进行交互时调用
- 此时的活动一定位于返回栈的栈顶,并且处于运行状态
onPause()
- 这个方法在系统准备去启动或者恢复另一个活动的时候调用
- 我们通常会在这个方法中将一些消耗 CPU 的资源释放掉以及保存一些关键数据
onStop()
- 这个方法在活动完全不可见的时候调用
- 它和 onPause() 方法的区别在于,如果启动的新活动是一个对话框样式的活动
- 那么 onPause() 方法会执行, onStop() 方法不会执行
onDestroy()
- 这个方法在活动被销毁之前调用
- 之后活动的状态将变为销毁状态
onRestart()
- 这个方法在活动由停止状态变为运行状态之前调用
- 也就是活动被重新启动了
以上七个方法除了 onRestart() 方法,其他都是两两相对的,从而又可以将活动分为三种生存期;
完整生存期
- 活动在 onCreate() 方法和 onDestroy() 方法之间所经历的就是完整生存期
- 一般情况下,一个活动会在 onCreate() 方法中完成各种初始化操作
- 而在 onDestroy() 方法中完成释放内存的操作
可见生存期
- 活动在 onStart() 方法和 onStop() 之间所经历的就是可见生存期
- 在可见生存期内,活动对于用户总是可见的,即便有可能无法和用户进行交互
前台生存期
- 活动在 onResume() 方法和 onPause() 方法之间所经历的就是前台生存期
- 这个生存期内,活动总是处于运行状态
- 此时的活动是可以和用户进行相互的,我们平时看到和接触最多的也是这个状态下的活动
活动生命周期示意图
•体验活动的生命周期
准备工作
新建一个项目,命名为 ActivityLifeCycleTest,并选择 Empty Activity;
进入项目,将模式结构改成 Project 结构;
接下来,我们需要额外新建两个 Empty Activity;
点击 app/src/main/java,在包下右击->New->Activity->Empty Activity;
新建的两个 Activity 分别命名为 NormalActivity和 DialogActivity;
接下来就是敲代码的环节了;
activity_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="this is a normal activity"
android:textSize="20sp"
android:layout_centerInParent="true"/>
</RelativeLayout>activity_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="this is a dialog activity"
android:textSize="20sp"
android:layout_centerInParent="true"/> </RelativeLayout>通过代码可以看出,这两个布局文件的代码几乎没有区别,只是显示的文字不同;
其实从名字上可以看出,这两个 Activity 一个表示普通活动,一个表示对话框活动;
但我们并没有对 .java 文件任何修改,在哪里体现出 DialogActivity 为对话框活动呢?
别着急,下面我们马上开始配置;
打开 AndroidManifest.xml 文件;
有没有发现什么不一样的?
没错,在 .DialogActivity 的配置中;
通过使用 android:theme="@style/Theme.AppCompat.Dialog" 将 DialogActivity 设置成对话框形式的主题;
接下来,我们修改 activity_main.xml 中的布局;
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical"> <Button
android:id="@+id/btn_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Normal Activity"
android:textAllCaps="false"/> <Button
android:id="@+id/btn_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Dialog Activity"
android:textAllCaps="false"/> </LinearLayout>可以看到,在该布局中加入了两个按钮;
btn_1 用于启动 NormalActivity,btn_2 用于启动 DialogActivity;
最后修改 MainActivity.java 中的代码;
MainActivity.java
public class MainActivity extends AppCompatActivity { public static final String TAG = "MainActivity";
private Button btn1;
private Button btn2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate: "); btn1 = findViewById(R.id.btn_1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,NormalActivity.class);
startActivity(intent);
}
});
btn2 = findViewById(R.id.btn_2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,DialogActivity.class);
startActivity(intent);
}
});
} @Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
} @Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: ");
} @Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: ");
} @Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart: ");
} @Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
} @Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: ");
}
}在 onCreate() 方法中,分别为两个按钮注册了点击事件,用于启动 NormalActivity 和 DialogActivity;
然后在 Activity 的 7 个回调方法中分别打印一句话,这样我们就可以通过观察日志的方式来更直观的理解活动的生命周期;
有关 Log 的用法,请参考我的这篇博客;
运行程序
这时,观察 logcat 中的打印语句;
可以看到,当 MainActivity 第一次被创建的时候,会依次执行 onCreate() , onStart() 和 onResume() 方法;
然后,点击第一个按钮,启动 NomalActivity;
启动 NomalActivity
观察 logcat 中的打印语句;
由于 NormalActivity 已经把 MainActivity 完全遮住了,因此 onPause() 方法和 onStop() 方法都会执行;
然后,按下 Back 键返回,观察 logcat 中的打印语句;
由于之前 MainActivity 进入了停止状态,所以 onRestart() 方法会执行;
之后又依次开始执行 onStart() 方法和 onResume() 方法;
注意此时不会执行 onCreate() 方法,因为 MainActivity 并没有被重新创建;
然后,点击第二个按钮启动 DialogActivity;
启动DialogActivity
观察 logcat 中的打印语句;
可以看到,只有 onPause() 方法得到了执行, onStop() 方法并没有执行;
这是因为 DialogActivity 并没有完全遮挡住 MainActivity,此时,MainActivity 只是进入了暂停状态,并没有进入到停止状态;
相应的,按下 Back 键返回,也应该只有 onResume() 方法执行;
最后在 MainActivity 下按 Back 键退出程序,打印信息如下所示;
依次会执行 onPausr() , onStop() , onDestroy() 方法,最终销毁 MainActivity;
Android 学习之活动的生命周期的更多相关文章
- android:activity活动的生命周期
掌握活动的生命周期对任何 Android 开发者来说都非常重要,当你深入理解活动的生命 周期之后,就可以写出更加连贯流畅的程序,并在如何合理管理应用资源方面,你会发挥的 游刃有余.你的应用程序将会拥有 ...
- Android学习整理之Activity生命周期篇
一.Activity生命周期说明 Activity的四种状态: ⒈活动状态(Active or Running):也称为运行状态,处于Activity栈顶,在用户界面中最上层,完全能被用户看到,能 ...
- android学习笔记28——Activity生命周期
Activity生命周期 Activity的活动状态由android已Activity栈的形式管理,当前活动的Activity位于栈顶.随着不同应用的运行,每个Activity都有可能从活动状态转入非 ...
- Android学习笔记:Activity生命周期详解
进行android的开发,必须深入了解Activity的生命周期.而对这个讲述最权威.最好的莫过于google的开发文档了. 本文的讲述主要是对 http://developer.android.co ...
- android学习笔记(5)Activity生命周期学习
每一个activity都有它的生命周期,开启它,关闭它,跳转到其他activity等等,都会自己主动调用下面某种方法.对这些个方法覆写后观察学习. protected void onCreate(Bu ...
- Android学习手记(2) Activity生命周期
1. 单个Activity的生命周期 当只有一个Activity的时候, 首先执行onCreate->onStart->onResume. 这时, 窗口便显示在屏幕上了. 然后我们按返回键 ...
- Android学习笔记----Activity的生命周期图示
转载,一目了然.
- Android学习笔记(五)——活动的生命周期
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 为了能写出流畅连贯的程序,我们需要了解一下活动的生命周期. 一.返回栈 Android 中的活动是可以层叠的. ...
- Xamarin.Android活动的生命周期
一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没有丢失.可以看出app的“生命”是掌握在系统手上的, ...
随机推荐
- js 快速排序 All In One
js 快速排序 All In One 快速排序 / Quick Sort "use strict"; /** * * @author xgqfrms * @license MIT ...
- 微信公众号 webfullstack
微信公众号 webfullstack weixin refs https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_C ...
- Web Components All In One
Web Components All In One Web Components https://www.webcomponents.org/ HTML Template Custom Element ...
- PIP & Python packages management
PIP & Python packages management $ python3 --version # OR $ python3 -V # Python 3.7.3 $ pip --ve ...
- mdn & remove & removeChild
mdn & remove & removeChild Element https://developer.mozilla.org/en-US/docs/Web/API/Element ...
- js 最简单的发布订阅模式
let _subscriber: any; function autorun(subscriber: Function) { _subscriber = subscriber; _subscriber ...
- NGK公链如何构建区块链数字经济商业帝国?
2020年对于区块链市场来说,重大的利好消息莫过于NGK公链的上线了.NGK公链其广泛的市场前景.顶尖的技术,一直备受众多大型机构以及投资者所看好.同时,NGK公链也不负众望,在上线以后,就开始落地到 ...
- Python数据结构与算法_搜索插入位置(07)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 示例 1: 输入: [1,3,5,6], 5输出 ...
- 你真的懂 MP4 格式吗?
MP4 文件格式又被称为 MPEG-4 Part 14,出自 MPEG-4 标准第 14 部分 .它是一种多媒体格式容器,广泛用于包装视频和音频数据流.海报.字幕和元数据等.(顺便一提,目前流行的视频 ...
- 五分钟学会generator函数
什么是generator函数? 常规函数只会返回一个单一值(或者不返回任何值). 而 Generator 可以按需一个接一个地返回("yield")多个值.它们可与 iterabl ...