一、Activity的生命周期
当activity处于应用中运行时,它的活动状态是由以activity栈的形式管理的。固随着不同应用的运行,每个activity都可能从活动状态转到非活动状态,也会从非活动状态转入活动状态,或者被系统杀死。固需要了解activity的生命周期。
Activity 的生命周期大致会经过如下四种状态:
A、活动状态:当前Activity位于前台,用户可见,可以获得焦点
B、暂停状态:其他Activity位于前台,该Activity依然依然可见,只是不能获得焦点
C、停止状态:该Activity不可见,失去焦点
D、消耗状态:该Activity结束,或所在的进程被杀死
在看下官方文档提供的Activity生命周期图:
当Activity组成的情况下的生命周期:
Activity Launched –> onCreate() – > onStart() –> onResume –> onPurase() –> onStop() –> onDestory() –> Activity shut down
先看下这个几个方法:Activity正常周期的时候
Activity Launched : 这个的是意思是activity启动,记住,只是启动,它还没有任务生命周期的特征。做一些准备工作:如创建视图对象,加载数据之类的。记得清单文件中也有Launched 的字样,属于activity的启动
onStart(): 这个方法是我们的activity进入可见状态,用户看到界面时会调用,但是,这个时候还不能交互,不能获得焦点,触发事件。
onResume(): 这个方法,是所有activity的生命周期的最终期待,因为它这个时候,已经可以进行交互了,在这里能看到最终的布局效果,能够触发事件了。此刻你的activity处于activity栈的顶端,等待与用于用户发生交互。(每当界面重写调回或重启是会调用此方法)
onPause() : 顾名思义:activity进入暂停状态。因为这个方法,表示当前activity不能交互了,就是说不能响应用户操作了,但是,这个时候,activity还是可以看到的,在这里,可以暂停动画等界面效果,比如被触发了对话框,或者被锁屏。
onStop():这个方法表示activity不能被用户看到,在这里,我们应该保存数据,停止一些消耗资源的事件,防止在不可见状态下被回收。比如转到其他activity的界面,或者被后台执行。
onDestroy():顾名思义:被毁灭了, 这个方法执行是就是就一切完了,这个方法将销毁所有视图,在这里应该释放一切占用的资源,比如 停止播放,网络请求等所有操作,只是销毁视图,不是销毁 activity 对象,。
当用户不想和我们的activityA进行交互了,跳转到activityB进行交互时,获取到某些数据或者用户自己的意图后又跳回到A了。
此时会调用方法onRestart() 在你的activity停止后被调用,在重新开始之前调用。返回会依次调用onRestart() ---onStart()p---onResume():
举一个简单的例子来看一看生命周期的运转:
写了二个activity,mainActivity和testActivity 来分析,代码如下
mainActivity:
package com.itheima.life;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("onCreate");
}
// 当activity销毁的时候调用
@Override
protected void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
// 当界面可见的时候调用
@Override
protected void onStart() {
System.out.println("onStart");
super.onStart();
}
// 当页面不可见的时候调用
@Override
protected void onStop() {
System.out.println("onStop");
super.onStop();
}
//当页面被重新启动的时候调用
@Override
protected void onRestart() {
System.out.println("onRestart");
super.onRestart();
}
//获取焦点 当按钮可以被点击了
@Override
protected void onResume() {
System.out.println("onResume");
super.onResume();
}
//当界面失去焦点 当按钮不可以被点击
@Override
protected void onPause() {
System.out.println("onPause");
super.onPause();
}
//点击按钮 跳转到 TestActivity页面
public void click(View v) {
Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);
}
}
testActivity的代码:(空白的界面,只有个屏幕只会显示testview)
package com.itheima.life;
import android.app.Activity;
import android.os.Bundle;
public class TestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
}
A:当应用被安装或者被完成杀死再次进入时,执行的方法:
B:当按了home键后,后台执行时候:注:如果长时间后台执行,可能会被垃圾回收机制杀死,执行onDestory()方法
C、按了button,跳转到testActivity界面时,执行的方法:
D、当退回到mainActivity时候或者从后台切回来的时候会执行的方法:
会先执行Restart()方法,在调onStart()方法显示当前activity,最后执行onResume()等待交互。
E、当被锁屏的时候会调用的方法:
onPause方法先停止交互---在调用onStop方法在界面被视频了什么都没有了,如果长时间没处理,可能会被垃圾回收。
F、解锁的时候会调用如下方法:
G:当从mainActivity按返回键退回菜单会执行如下方法:
H、横竖屏的切换时,我们发现系统会先将当前Activity销毁,然后重建一个新的,方法流程如下
onPause---onStop---onDestory ---onCreate ---onStart---onResume
为了避免这样销毁重建的过程,我们需要在AndroidMainfest.xml中对OrientationActivity对应的<activity>配置android:configChanges="orientation" 再每次旋转不会销毁重建的过程,只会调用方法onConfigurationChanged
二、Activity的4种启动模式
启动模式简单地说就是Activity启动时的策略,在AndroidManifest.xml中的标签的android:launchMode属性设置;
启动模式有4种,分别为standard、singleTop、singleTask、singleInstance;
先用简单说下任务栈,每个应用都有一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity的出现顺序;比如Activity1-->Activity2-->Activity3,则任务栈为:
A、standard:standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈;
默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
点back键会依照栈顺序依次退出。一层一层的返回。
清单配置如下:默认不用配置
B、singleTop:如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例;
就是允许多个不一样的实例,但是启动在栈堆重复的Activity就要把旧的复用。
清单配置如下:
<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/_second"
android:launchMode="singleTop">
</activity>
重复的复用会执行到栈顶,返回的时候为2---3---1
C、singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。一人一个模式。
清单配置如下:
<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/_second"
android:launchMode="singleInstance">
</activity>
D、singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都取消;
如果ActivityB由另外一个程序启动:假设apkA是情况一中的应用,apkB是另外一个测试程序,在apkB中启动apkA中的ActivityB,再分两种情况,如果ActivityB未启动过,刚ActivityB会位于栈底,是根元素,会启动新的task;如果ActivityB启动过,则ActivityB保持原来的位置不变,在栈底或者栈顶,移除掉ActivityB之上所有的activity(如果有),见下图
相当有一条水平面,Activity相对于一连串的盒子放在水中(安装调用顺序从下到上,最新调用在最上面)。每当启动Activity时,该Activity位于水平面位置,上面的所有其他Activity会被杀死。即谁被调用就冒到水平面。上面的被杀死。
清单配置如下:
<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/_second"
android:launchMode="singleTask">
</activity>
总结:Activity的生命周期图要记住,了解每个方法在什么时候被调用,了解其生命周期的机制,才能更好的设计程序和运行机制。
Activity的4中启动方式,最好用图片的模式记住,印象更深刻!会画4中启动方式的栈图。别忘记配置清单文件