一、概述:
Activity是android的四大组件之一,是用户接口程序,它会提供给用户一个交互式的接口功能。它是 android 应用程序的基本功能单元,其实Android中的Activity运行机制跟servlet有些相似之处,Android系统相当于servlet容器,Activity相当于一个servlet,我们的Activity处在这个容器中,一切创建实例、初始化、销毁实例等过程都是容器来调用的 ,activity 本身是没有界面的。所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上。
二、生命周期
1、onCreate: 在这里创建界面,做一些数据的初始化操作
2、onStart: 用户可见但不可交互的状态
3、onResume: 可与用户交互的状态(Activity的栈系统通过栈的方式管理Activity)
4、onPause:用户可见不可交互状态,系统会停止动画等消耗CPU的事情,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来。
5、onStop:不可见,被下一个Activity覆盖
6、onDestroy:这是Activity被kill前最后一个被调用方法了,可能是其他类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个Progress Dialog在线程中运行,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常。onPause,onstop, onDestroy,三种状态下 activity都有可能被系统kill 掉。
package com.example.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private static final String TAG = "LifeCycleActivity";
private int param = 1;
private Button button;
//activity创建时被调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate called.");
setContentView(R.layout.activity_main);
button = (Button) this.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this,TargetActivity.class);
startActivity(intent);
}
});
}
//activity创建时或者后台重新回到前台时被调用
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.i(TAG, "onStart called.");
}
//activity从后台重新回到前台时被调用
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.i(TAG, "onRestart called.");
}
//Activity创建或者从被覆盖、后台重新回到前台时被调用
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.i(TAG, "onResume called.");
}
//Activity被覆盖到下面或者锁屏时被调用
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.i(TAG, "onPause called.");
//有可能在执行完onPause或onStop后,系统资源紧张将Activity杀死,所以有必要在此保存持久数据
}
//退出当前Activity或者跳转到新Activity时被调用
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.i(TAG, "onStop called.");
}
//退出当前Activity时被调用,调用之后Activity就结束了
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i(TAG, "onDestroy called.");
}
//Activity窗口获得或失去焦点时被调用,在onResume之后或onPause之后
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
Log.i(TAG, "onWindowFocusChanged called.");
}
/**
* Activity被系统杀死时被调用.
* 例如:屏幕方向改变时,Activity被销毁再重建;当前Activity处于后台,系统资源紧张将其杀死.
* 另外,当跳转到其他Activity或者按Home键回到主屏时该方法也会被调用,系统是为了保存当前View组件的状态.
* 在onPause之前被调用.
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
Log.i(TAG, "onSaveInstanceState called.");
super.onSaveInstanceState(outState);
}
/**
* Activity被系统杀死后再重建时被调用.
* 例如:屏幕方向改变时,Activity被销毁再重建;当前Activity处于后台,系统资源紧张将其杀死,用户又启动该Activity.
* 这两种情况下onRestoreInstanceState都会被调用,在onStart之后.
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i(TAG, "onRestoreInstanceState called.");
super.onRestoreInstanceState(savedInstanceState);
}
}
过程:
1、启动Activity,首先会调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。
2、当Activity被其他Activity覆盖或者锁屏时,系统会调用onPause方法,暂停当前Activity的执行。
3、当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
4、当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
5、用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
6、当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
7、用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。
8、onWindowFocusChanged方法:在Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。以上几种情况都会调用onWindowFocusChanged,并且当Activity被创建时是在onResume之后被调用,当Activity被覆盖或者退居后台或者当前Activity退出时,它是在onPause之后被调用,如图所示:
这个方法在某种场合下还是很有用的,例如程序启动时想要获取视特定视图组件的尺寸大小,在onCreate中可能无法取到,因为窗口Window对象还没创建完成,这个时候我们就需要在onWindowFocusChanged里获取。
9、onSaveInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用;(2)在用户改变屏幕方向时,此方法会被调用;(3)在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用。第一种情况我们无法保证什么时候发生,系统根据资源紧张程度去调度;第二种是屏幕翻转方向时,系统先销毁当前的Activity,然后再重建一个新的,调用此方法时,我们可以保存一些临时数据;第三种情况系统调用此方法是为了保存当前窗口各个View组件的状态。onSaveInstanceState的调用顺序是在onPause之前。
10、onRestoreInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity,此方法会被调用;(2)在用户改变屏幕方向时,重建的过程中,此方法会被调用。我们可以重写此方法,以便可以恢复一些临时数据。onRestoreInstanceState的调用顺序是在onStart之后
三、横竖屏切换
package com.example.activity;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private int param = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orientation_portrait);
Log.i(TAG, "onCreate called.");
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart called.");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "onRestart called.");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume called.");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause called.");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop called.");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestory called.");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("param", param);
Log.i(TAG, "onSaveInstanceState called. put param: " + param);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
param = savedInstanceState.getInt("param");
Log.i(TAG, "onRestoreInstanceState called. get param: " + param);
super.onRestoreInstanceState(savedInstanceState);
}
//当指定了android:configChanges="orientation"后,方向改变时onConfigurationChanged被调用
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(TAG, "onConfigurationChanged called.");
switch (newConfig.orientation) {
case Configuration.ORIENTATION_PORTRAIT:
setContentView(R.layout.orientation_portrait);
break;
case Configuration.ORIENTATION_LANDSCAPE:
setContentView(R.layout.orientation_landscape);
break;
}
}
}
一.无设置configChanges属性
1、旋转屏幕
旋转屏幕时,系统会先将当前Activity销毁,然后重建一个新的,系统先是调用onSaveInstanceState方法,我们保存了一个临时参数到Bundle对象里面,然后当Activity重建之后我们又成功的取出了这个参数。
如果要避免重新创建,我们需要在AndroidMainfest.xml中对OrientationActivity对应的配置android:configChanges=”orientation”;
* 二.在AndroidManifest里添加configChanges的orientation属性
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.screen" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
做了四次旋转,可以看到,每次旋转方向时,只有onConfigurationChanged方法被调用,没有了销毁重建的过程。
以下是需要注意的几点:
1.如果配置了android:screenOrientation属性,android:configChanges=”orientation”失效。
2.模拟器与真机差别很大:模拟器中如果不配android:configChanges属性或配置值为orientation,切到横屏执行一次销毁->重建,切到竖屏执行两次。真机均为一次。模拟器中如果配置android:configChanges=”orientation|keyboardHidden”(如果是Android4.0,则是”orientation|keyboardHidden|screenSize”),切竖屏执行一次onConfigurationChanged,切横屏执行两次。真机均为一次。
Activity的生命周期与程序的健壮性有着密不可分的关系,希望朋友们能够认真体会、熟练应用。