随着用户进入、离开、再进入等动作,我们的Activity不停的在其生命周期的几个状态之间来回切换,比如,当用户点击桌面上的应用程序图标时,我们的主Activity被启动,这时,系统会调用一系列的生命周期回调函数来完成Activity的创建及显示工作;当用户切换到另一个Activity的时候,当前Activity的一系列生命周期方法又被调用。在程序的执行过程中,Activity会在其生命周期的各个状态之间不停的转换。根据我们所需的Activity的复杂度,我们可能不需要实现所有的生命周期回调函数,但是我们有必要理解每一阶段是怎么一回事,这样方可确保我们所写程序的表现符合用户的期望,一般来说,我们应该遵守以下几点基本要求:
- 当用户由于接到一电话或者其他原因切换到另一个程序时,我们的程序不能出问题
- 当用户不再使用我们的程序的时候,我们的程序不应该继续消耗有价值的系统资源
- 当用户离开一段时间然后又回到程序时,先前的进度不能丢失
- 当由于屏幕方向切换时我们的程序能够表现正常(实现方法后边会说)
一个Activity只会有六种状态,Created、Started、Resumed、Paused、Stopped、Destoryed。其中Activity在Created、Started、Destoryed这三个状态上不会做停留,也就是说从这一状态很快会过渡到下一状态。另外三种状态如果想发生转移的话是需要有条件触发的,这三种状态的含义如下:
- Resumed:此时Activity在前景并且可以和用户进行交互
- Paused:此时Activity部分可视,但是不能和用户交互
- Stopped:此时用户完全不可视(被全部遮挡了),但是依然会被保留到内存中
从Activity被Create到其被Destory,可以将这一过程比作爬阶梯型的金字塔,其中Resumed状态为金字塔的顶端。从创建到可视并可以获得焦点,经历三个步骤就从金字塔的一边爬到了顶端;当用户离开当前Activity的时候,可比作下金子塔,当然以后还有可能会再次回退到顶部,这个类比过程可用下图说明:
启动Activity:我们应该为我们的应用程序设定一个主Activity,做到这点很容易,只需在清单文件(AndroidManifest.xml)中对要设定为主Activity的组件做如下声明:
<activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
其中的<intent-filter>中的action和category必须做如上声明,只要其中有一个不满足,则在我们的程序图标就不会出现在系统桌面上。
要想启动一个Activity,我们必须为其提供onCreate()方法,这也是唯一一个我们必须实现的方法,在这个方法中我们应该做一些在Activity的生命周期中只需执行一次的事情,比如设置用户界面、初始化一些类作用域的变量等。如下下边的例子所示,在onCreate()中这是了界面,初始化了将要在程序代码中引用的控件。
TextView mTextView; // Member variable for text view in the layout @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set the user interface layout for this Activity // The layout file is defined in the project res/layout/main_activity.xml file setContentView(R.layout.main_activity); // Initialize member TextView so we can manipulate it later mTextView = (TextView) findViewById(R.id.text_message); // Make sure we're running on Honeycomb or higher to use ActionBar APIs if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // For the main activity, make sure the app icon in the action bar // does not behave as a button ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(false); } }
在调用onCreate函数之后,会很快调用onStart(),当调用这个函数时,Activity就已经可以在屏幕上看到了;在这个状态也不会过多停留(如前所述),紧接着调用onResume(),这个函数执行之后,Activity便可以和用户交互了,这是一个Activity遍完成了启动过程,并且会停留在这一状态,除非有其他的事情发生,比如用户点击了某个按钮启动了另外一个Activity。启动过程共三步,可用下图表示:
销毁Activity:正如onCreate()是被第一个调用的,onDestory()是被最后调用的,调用这个函数表明系统将会把这个Activity从内存中移除。大多数情况下我们没有必要重写这个方法,因为大部分的清理工作应该在onPause()和onStop()方法中完成,但是,如果我们在onCreate()中启动了某些线程之类,会长期占用系统资源,如果不清理会造成内存泄露,那么我们应该在onDestory()中将其关闭。如下所示,在onDestory()中,关闭了调试时用的方法调用痕迹。
@Override public void onDestroy() { super.onDestroy(); // Always call the superclass // Stop method tracing that the activity started during onCreate() android.os.Debug.stopMethodTracing(); }
一般情况下,系统会在调用onPause()和onStop()之后调用onDestory(),但是有一特例,如果我们在onCreate()中调用了finish(),则不会调用onPause()和onStop(),直接调用onDestory()。
Pausing和Resuming:当用户执行其它动作将当前Activity部分遮挡的时候,就会进入Paused状态,这时会调用onPause()方法,这意味着用户离开当前Activity,并且有可能不会再回来了,在这个方法中,我们应该做如下工作:
- 停止那些消耗CPU工作
- 保存那些尚未存储的更改,当然,只能保存用户希望我们保存的,比如编辑了一部分的邮件。但是我们不应该在这个函数中执行一些费时的工作,不如写数据库,像这类比较耗时繁重的工作应该在onStop()中完成,这样做的目的是希望可以快速的过渡到下一个状态。
- 释放一些在暂停状态下不用的资源,不如广播接受者等
下面的例子在onPause()中释放了一个相机资源:
@Override public void onPause() { super.onPause(); // Always call the superclass method first // Release the Camera because we don't need it when paused // and other activities might need to use it. if (mCamera != null) { mCamera.release() mCamera = null; } }
当用户从暂停状态返回时,将会调用onResume(),这里我们应该将在onPause()中释放的资源重新获取,注意一点,这个方法在启动过程中也是会被调用的。如下示例为在onResume()中重新获取了相机资源:
@Override public void onResume() { super.onResume(); // Always call the superclass method first // Get the Camera instance as the activity achieves full user focus if (mCamera == null) { initializeCamera(); // Local method to handle camera init } }
Pausing和Resuming过程可用下图详细说明:
Stopping and Restarting:合理的处理这一过程是很重要的,因为我们应该让用户感到应用程序一直都没有关闭,先前的进度还在。下面有几个典型的情况需要用到stop然后restart的过程:
- 用户切换到另一个程序,当前Activity被stop,然后用户有回到当前程序,这时我们应该restart离开时的Activity。
- 用户在当前Activity执行了一个动作使得启动了另一个activity,当前Activity被stop,另一个Activity被启动,过了一会儿,用户按了返回键,当前ACtivity应该被restart。
- 用户接了一个电话后,先前的Activity应该被restart。
当onStop()被调用,意味着当前Activity完全不可见,这是我们应该释放几乎是全部的系统资源,因为在某些极端情况下,系统有可能都不会调用onDestory()来终止当前Activity,所以我们一般在这里释放那些比较费时的释放工作,比如说写数据库。
当用户再次将Activity从Stop状态激活时,将会调用onRestart(),之后也会调用onStart()。其实,onRestart()并不是很常用,因为其后会调用onStart(),而onStart()无论是在Activity第一次启动,还是从Stop状态恢复都会被调用,通常所有的工作都会在onStart()中完成。
整个Stop和Restart过程可以用下图说明:
Recreate Activity:重建Activity。如果Activity是正常终止的话,那么这个过程不需要;但是如果是由于系统资源不足,而终止了那些当前不用的Activity,那么系统会记住这一情况,当用户再次回到该Activity的时候,系统会利用销毁这个Activity时记录的一个Buble对象进行重建。若要实现这个重建,需要我们重写onSaveInstanceState()方法,这个方法返回一个Buble对象。当这个Activity被“非预期”销毁时,系统会调用这个方法,然后如果确实需要重建的时候,将会把这个方法传递给onCreate()和onRestoreInstanceState()。如下例:
static final String STATE_SCORE = "playerScore"; static final String STATE_LEVEL = "playerLevel"; ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state savedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); // Always call the superclass so it can save the view hierarchy state super.onSaveInstanceState(savedInstanceState); }
因为在重建的时候,这个Buble会被传递给俩个方法,onCreate()和onRestoreInstanceState(),所以我们选其中一个实现即可,只不过onCreate()在第一次创建时也会被调用,所以需要判断一下Buble是否为空,以此来区分这俩种状态,在onRestoreInstanceState()中就不存在这样的情况。重建过程如下图:
这篇博客中的内容来自对Android官方文档的理解,更权威的内容请参考官方文档。鉴于本人也是新手,纰漏之处在所难觅,欢迎批评指正。本人QQ联系方式:750516366,欢迎交流。