Activity生命周期
在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。
Activity有四种本质区别的状态:
下面的图显示了Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。
在上图中,Activity有三个关键的循环:
Android 状态
下面的 Activity 方法定义了 activity 完整的生命周期。他们全都是 hook 方法,你可以重载这些方法从而使 activity 在状态改变时执行你所期望的操作。所有activity 都应该实现自己的 onCreate(Bundle)方法来进行初始化设置;大部分还应该实现 onPause()方法提交数据的修改并且准备终止与用户的交互。尽管我们计划在系统中添加更多的工具来管理应用,现在大多 activity 仍需要实现 onFreeze()并且在 onCreate(Bundle)中执行对应的状态恢复。其他的方法可以在需要时进行实现,当实现这些方法的时候需要注意的是一定要调用父类中的对应方法
测试生命周期的小例子:
package com.android.com; import android.app.Activity; import android.util.Log; public class androidLifeTest extends Activity { /** Called when the activity is first created. */ private static final String TAG="AndroidLife"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.i(TAG, "onCreate"); } protected void onStart(){ super.onStart(); Log.i(TAG, "onStart"); } protected void onResume(){ super.onResume(); Log.i(TAG, "onResume"); } protected void onStop(){ super.onStop(); Log.i(TAG, "onStop"); } protected void onPause(){ super.onPause(); Log.i(TAG, "onPause"); } protected void onDestory(){ super.onDestroy(); Log.i(TAG, "onDestory"); } protected void onRestart(){ super.onRestart(); Log.i(TAG, "onRestart"); } protected void onPostCreate(Bundle savedInstanceState){ super.onPostCreate(savedInstanceState); Log.i(TAG, "onPostCreate"); } protected void onPostResume(){ super.onPostResume(); Log.i(TAG, "onPostResume"); } public void onContentChanged(){ super.onCreateDescription(); Log.e(TAG, "============> onContentChanged[1]"); } }
首先我们看到的最上面的画面是最重要的,并且也是焦点所在。此时可以通过函数onWindowFocusChanged()来判度。此时activity在栈顶。
在onCreate()-->onContentChanged()-->onStart的过程中还要涉及到一些内部方法的调用,我们来看一下:
onWindowAttributesChanged(WindowManager.LayoutParams params) 当当前窗口属性更改时被调用。
public void onContentChanged() 当屏幕的目录视图改变(因调用 Window.setContentView 或Window.addContentView))时此钩子被调用。
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first)
由setTheme(int) 和 getTheme()调用于应用一个主题资源到当前Theme对象。 可以覆盖更改默认的(简单)的行为。这种方法不会被称为多线程。
我们分情况讨论一下:
(1)只有一个activity的时候:
流程如下: onCreate()-->onStart()-->onResume() 现在就是用户看到的界面如果,
按下back键,activity的生命周期将会结束。流程:onPause()-->onStop()-->onDestroy();
如果按下Home键,首先会保存当前activity的实例状态。OnSaveInstanceState(), 然后转入后台处理,onPause(),最后onStop();当前activity界面状态不可见。
(2)如果有多个activity,并且在启动第二个activity后,调用finish()函数。当从第一个activity跳转到第二个activity的时候,当第二个
activity正要显示出来的时候,第一个activity会执行onPause()方法,转入后台。同时第二个activity执行onCreate()-->onStart()-->onResume().显示出界面。
第一个activity继续执行onStop()-->onDestory()方法。第一个activity生命周期结束。同样,多个activity在彼此调用后,都是这样的流程。
(3)如果有多个activity,并且在启动第二个activity后,没有调用finish()函数。
流程如下: onCreate()-->onStart()-->onResume() 现在就是用户看到的界面。如果,按下back键,activity的生命周期将会结束。流程:onPause()-->onStop()-->onDestroy();
如果按下Home键,首先会保存当前activity的实例状态。OnSaveInstanceState(), 然后转入后台处理,onPause(),最后onStop()。
如果继续跳转activity,并利用back键返回前一个activity,流程如下:onRestart()-->onStart()-->onResume()-->onStop()-->onDestory().前一个activity生命周期结束。
怎样保存Activity的状态:
当一个 Activity 被 kill 之前,它可以调用 onSaveInstanceState()来保存当前 activity的状态信息。用来保存状态信息的 Bundle 会同时传给两个 method,即
onRestoreInstanceState() and onCreate().
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("Boolean", true);
outState.putDouble("Double", 1.9);
outState.putInt("Int", 1);
outState.putString("String", "Welcome back to Android");
// etc.
这样,在activity转换的时候我们可以把我们要保存的数据值通过Bundle来保存到onCreate()中,等待下一次的初始化。同样在onRestoreInstanceState()中接受到要保存的信息:
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
boolean myBoolean = savedInstanceState.getBoolean("Boolean");
double myDouble = savedInstanceState.getDouble("Double");
int myInt = savedInstanceState.getInt("Int");
String myString = savedInstanceState.getString("String");
}
多个 activity 之间传输数据的主要方法
(1)bundle+Intent
举例如下:
我们可以在比如按钮事件中加入以下代码来实现 activity 的跳转和数据传入
Intent intent = new Intent();
intent.setClass(A.this,B.class);
Bundle bundle = new Bundle();
bundle.putDouble("height",height);
bundle.putString("sex",sex);
intent.putExtras(bundle);
startActivity(intent);
同时在 B 的 activity 中,我们必须要接受数据,并本地化这些数据。
Bundle bunde = this.getIntent().getExtras();
String sex = bunde.getString("sex");
double height = bunde.getDouble("height");
现在 activity 之间的数据传递已经完成,我们可以在 B 中使用 A 传来的这些数据。如果想从 B 中返回要得到的数据可以使用 startActivityForResult()方法。
好,我们现在来看一下是怎样传输的,其中都包含了什么?首先我们定义了 Bundle 的实例,作为存储数据的对象,利用 put 来把要传输的数据放入 bundle 这个实例中,我们来看一下效果
Bundle[{sex=M, height=172.0}]
这就是在传输过程中 Bundle 实例中的内容,利用 get 方法来获取到其中的内容。
注意类型的匹配。