Activity
Activity是Android程序的4大组件之一。
Activity是Android程序的表示层。程序的每一个显示屏幕就是一个Activity。
学过WEB开发者,可以把Activity理解成网页中的一个JSP文件;或者你可以把它理解成一个Windows的窗口。
下面看一下Activity类的继承关系:
从这里可以看到Activity是Context类的子类。
Activity的生命周期
当用户的焦点进入,离开,或返回时,应用程序中的activity会在它们生命周期中的不同状态进行转换,比如,当activity第一次创建时,它会位于系统屏幕最前面接受用户焦点,在这一过程中,系统会调用activity上的一系列生命周期方法,从而成生用户界面或其它组件
Activity的生命周期不是自身控制的,而是由Android系统控制的。
虽然不是每一次的交互都会经历所有的生命周期方法,但对生命周期方法的了解是很重要的,才能更好的了解跟满足用户对系统行为的要求:
- 当用户接到电话或切换其它的应用程序时,不要突然消毁;
- 当用户不处理活动状态时,不要过份的消耗系统资源;
- 当用户焦点离开,不久又返回到应用程序时,不要丢失用户的流程数据;
- 当用户在横屏与竖屏之间切换时,不要消毁或丢失用户流程数据。
在android中Activity有四种基本状态:
1、Running
位于屏幕最前端时,此时处于可见状态,和用户可交互的状态(也叫Resumed)。
2、Paused
当Acitivy被另一个透明的或者非全屏的Activity覆盖时的状态叫Paused状态,虽然可见但不可交互。
3、Stopped
当Activity被另外一个Activity覆盖、界面不可见时处于Stop状态。
4、Killed
Activity被系统杀死或者跟本没启动时就是Killed状态。
其它的状态(Created和Started)是短暂的,系统通过调用下一下生命周期方法很快从它们转向下一个状态,可以这么说,当系统调用onCreate()后,会很快的调用onStart(),紧接着很快的调用onResume()
我们下面看一下Activity的生命周期:
指定系统起动自动加载APP,(程序入口)
当用户起动应用程序时,系统调用被声明为launchar(或main)的Activity的onCreate()方法,这一方法通过AndroidManifest.xml实现
例如:
<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>
创建一个新的实例
大多数程序都包含很多不同功能的Activity,系统通过调用Activity的Oncreate()方法对它们进行创建,我们可以通过onCreate()方法实现基本的程序起动逻辑,针对某些只需要在整个生命周期中只执行一次的逻辑,
一旦onCreate()方法执行完成,onStart()和onResume()紧接着会被调用,当onStart()被调用时用户界面是可见的了,然后调用onResume()方法,从此,Activity保持resumed状态直到某些操作改变了这一状态,如电话打进来,用户切换到另一个Activity或用户关闭屏幕等。
挂起Activity
当系统调用onPause()时,意味着你的Activity挂起,部分可见,最常见的就是用户焦点离开,过一段时间就会进入到Stoped状态,我们经常使用onPause()来实现以下操作:
- 停止活跃的或其它正在进行的占用CPU的处理;
- 提交善未保存的更改,当用户离开时,只接受用户持久化的存储;
- 释放系统资源,如广播接受者,GPS或其它浪费,响影系统电源的资源。
比如,如果你的程序使用相机, the 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; } }
一般情况下,我们不建议在onPause()存储用户的更改到持久化设备,唯一能使用这一方法进行此操作的情况是你确信用户需要把他的更改自动存储
Note: When your activity is paused, the Activity
instance is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state.
恢复Activity
当Activity从挂起状态被用户恢复时,系统调用onResume()方法。
值得注意的是,当你的Activity被切到屏幕前面,获得焦点时,这个方法都会被调用,把括第一次被创建时,因此,我们必须在onRsume()里初始化那些在onPsuse()里被释放的组件跟那些Activity进入恢复状态都必须初始化的操作,
下面的例子初始化我们在onPause()里释放的相机实例;
@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 } }
停止Activity
什么况下会停止Activity:
- 当用户切换到另外的应用程序,你应用程序当前的Activity将停止,当用户从程序国标或现在应用程序返回到你的Activity时,Activity将会重新启动;
- 当你的应用程序开启一个新的Activity时,当新的Activity被创建时当前的Activity将会停止,如果现在用户按返回按钮,原先的Activity将会重新启动;
- 当用户正在使用你的程序,收到来电时
在停止的状态下,整个Activity都是不可见的,
Note: Because the system retains your Activity
instance in system memory when it is stopped, it's possible that you don't need to implement theonStop()
and onRestart()
(or even onStart()
methods at all. For most activities that are relatively simple, the activity will stop and restart just fine and you might only need to use onPause()
to pause ongoing actions and disconnect from system resources.
当系统调用onStop()方法时,Activity将不可见,且系统必须释放几乎所有用户不再使用的资源,虽然onPause()在onStop()之前被调用,但最好使用onStop()进行大型,占用CPU的操作,比如将数据存储到数据库中。
@Override
protected void onStop() {
super.onStop(); // Always call the superclass method first
// Save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
当Activity停止时,其实例还是驻在内存中,当Activity恢复时,它会被重新调用,我们不需要重新初始化组件,系统同时会跟踪布局中所有视图的当前状态,所以如果用户输入TEXT到Editext widget,我们不需要保存或再次重新加载它,在恢复时内容会保留。
Note: Even if the system destroys your activity while it's stopped, it still retains the state of the View
objects (such as text in an EditText
) in a Bundle
(a blob of key-value pairs) and restores them if the user navigates back to the same instance of the activity (the next lesson talks more about using a Bundle
to save other state data in case your activity is destroyed and recreated).
启动或重启你的Activity
当你的Activity从停止状态重新获得焦点时,系统将调用onRstart()方法,系统同时也会调用onStart()方法,onStart()每次都会被调用,不管你是恢复Activity还是第一次创建Activity,但onRestart()只当Activity从停止状态恢复时被调用,你可以用它来做一些只当Activity从停止状态恢复时才需要做的恢复工作。
因为onStop()清理你Activity所有的资源,当Activity重新启动时,我们必须重新初始化这些资源,另外,当我们第一次创建Activity实例时,我们也必须初始化这些资源,因此,我们通常使用onStart()作为onStop()的镜像操作方法,因为当Activity第一次创建或从停止状态恢复时,都会调用onStart()方法。
比如:
because the user might have been away from your app for a long time before coming back it, the onStart()
method is a good place to verify that required system features are enabled:
@Override protected void onStart() { super.onStart(); // Always call the superclass method first // The activity is either being restarted or started for the first time // so this is where we should make sure that GPS is enabled LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (!gpsEnabled) { // Create a dialog here that requests the user to enable GPS, and use an intent // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action // to take the user to the Settings screen to enable GPS when they click "OK" } } @Override protected void onRestart() { super.onRestart(); // Always call the superclass method first // Activity being restarted from stopped state }
销毁Activity
生命周期的最后一个方法是onDestroy,当Activity实例完成后被从系统内存中移除时调用,大多数应用程序不用重写实现这一方法,大多数的清理工作建议放在onPause()要onStop()方法中实现,但是,如果你的应用程序包含后台线程或其它占用资源的可以导致内存泄露的任务,我们必须在onDestroy()中杀了这些进程。
Note: The system call onDestroy() after it has already called onPause() and onStop() in all situations except one: when you call finish()from within the onCreate() method. In some cases, such as when your activity operates as a temporary decision maker to launch another activity, you might call finish() from within onCreate()
to destroy the activity. In this case, the system immediately calls onDestroy()
without calling any of the other lifecycle methods.
重新创建Activity
以下情况系统会销毁Activity:
1,当用户按下Back按钮或者你的Activity用finish()指定销毁实例
2,当Activity长时间停止且不再被使用,当前的Activity要求更多的系统资源时,系统可能会销毁后台的Activity以释放内存空间。
第一种情况,系统认为此实例可以不用重新创建,用户行为已表明此实例是不再需要的。但是,如果Activity是让系统强制销毁,虽然实例已被销毁,但系统会记下被销毁的Activity的状态,当用户焦点再次回到此Activity时,系统会使用保存下来的数据重新创建Activity,这些保存下来的数据叫”Insance state”,是存储在Bundle对象中的key-value 对。
默认情况下,系统使用Bundle对象保存Activity布局中每一个view的信息(如EditText中输入的内容),所以,当Activity被重新创建时,布局状态自动恢复到之前的状态,但是,我们可能想保存更多的状态信息,
onSaveInstanceState()
和 onRestoreInstanceState()可以帮到我们,当用户离开Activity时,
onSaveInstanceState()会被调用,
Bundle
对象会当参数传给它,我们可以添加额外想要的信息。当系统需要重新创建Activity时,同样的 Bundle
对象会传给 onRestoreInstanceState()
方法,同时传给onCreate()完成Activity的重新创建。
下面举一下例子:
当Activity准备停止时, 系统调用 onSaveInstanceState()
方法,所以Activity采用Key-value对的方法保存状态信息,为了保存额外的信息,我们必须重写 onSaveInstanceState()
方法;
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); }
当Activity销毁后重新创建时,我们可以利用Bundle对象实现Activity状态的复原。
如果我们在onCreate()中恢复状态,因为 onCreate()
方法在系统第一次新建Activity实例或Activity得新创建时都会被调用,我们必须判断bundle对象是不是为NULL
For example, here's how you can restore some state data in onCreate()
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance if (savedInstanceState != null) { // Restore value of members from saved state mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance } ... }
用 onRestoreInstanceState()实现状态复原
, 系统调用 onStart()
后将调用此方法.系统只会在有状态需要复原时才会调用onRestoreInstanceState(),所以不需要判断bundle对象是不是为NULL,如下:
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }
Activity栈(转):
Android通过Activity栈的方式来管理Activity。
正在运行的Activity 处在在栈的最顶端,它是运行状态的;
当有新Activity进入屏幕最上端时,原来的Activity就会被压入第二层,如果他的屏幕没有被完全遮盖,那么他处于Pause状态,如果他被遮盖那么他处于Stop状态。
当然不管你出于任何一层,都可能在系统觉得资源不足时被强行关闭,当然关闭时在栈底的程序最先被关闭。
譬如:当你在程序中调用 Activity.finish()方法时,结果和用户按下 BACK 键一样:他告诉 Activity Manager该Activity实例可以被“回收”。随后 Activity Manager 激活处于栈第二层的 Activity 并重新入栈,把原 Activity 压入到栈的第二层,从 Running 状态转到 Paused 状态。
实例:观察翻转屏幕导致的Activity状态变化
Activity类中定义了和生命周期相关的一些方法,这些方法会在状态改变时被调用,譬如创建时调用的方法onCreate()。因此我们可以写一个程序,在程序的每个一个方法中写注释,然后看看运行时注释的打印顺序来跟踪Activity的状态变化。