您的应用中的Activity应该做到如下需求:
1.用户在使用应用时接听来电或切换到另一个应用,它不会崩溃。
2.在用户未主动使用它时不会消耗宝贵的系统资源。
3.如果用户离开您的应用并稍后返回,不会丢失用户的进度。
4.当屏幕在横向和纵向之间旋转时,不会崩溃或丢失用户的进度。
,Activity只能在三种状态之一下存在很长时间。
Resumed:在这种状态下,Activity处于前台,且用户可以与其交互。(有时也称为“运行”状态。)
Paused:在这种状态下,Activity被在前台中处于半透明状态或者未覆盖整个屏幕的另一个Activity—部分阻挡。暂停的Activity不会接收用户输入并且无法执行任何代码。
Stopped:在这种状态下,Activity被完全隐藏并且对用户不可见;它被视为处于后台。停止时,Activity实例及其诸如成员变量等所有状态信息将保留,但它无法执行任何代码。
当用户从主界面点击程序图标时,系统会调用app中被声明为"launcher" (or "main") activity中的onCreate()方法。这个Activity被用来当作程序的主要进入点。
我们可以在AndroidManifest.xml中定义作为主activity的activity。
这个main activity必须在manifest使用包括MAINaction 与LAUNCHERcategory 的标签来声明。例如:
onCreate()方法中定义UI以及实例化类成员变量
一旦onCreate 操作完成,系统会迅速调用onStart()
与onResume()方法。我们的activity不会在Created或者Started状态停留。技术上来说,
activity在onStart()被调用后开始被用户可见,但是
onResume()会迅速被执行使得activity停留在Resumed状态,直到一些因素发生变化才会改变这个状态。例如接收到一个来电,用户切换到另外一个activity,或者是设备屏幕关闭。
销毁Activity
activity的第一个生命周期回调函数是 onCreate(),它最后一个回调是onDestroy().当收到需要将该activity彻底移除的信号时,系统会调用这个方法。大多数app并不需要实现这个方法,因为局部类的references会随着activity的销毁而销毁,并且我们的activity应该在onPause()与onStop()中执行清除activity资源的操作。然而,如果activity含有在onCreate调用时创建的后台线程,或者是其他有可能导致内存泄漏的资源,则应该在OnDestroy()时进行资源清理,杀死后台线程。@OverridepublicvoidonDestroy(){super.onDestroy();// Always call the superclass// Stop method tracing that the activity started during onCreate()android.os.Debug.stopMethodTracing();}Note:除非程序在onCreate()方法里面就调用了finish()方法,系统通常是在执行了onPause()与onStop() 之后再调用onDestroy() 。在某些情况下,例如我们的activity只是做了一个临时的逻辑跳转的功能,它只是用来决定跳转到哪一个activity,这样的话,需要在onCreate里面调用finish方法,这样系统会直接调用onDestory,跳过生命周期中的其他方法。
暂停与恢复Activity
当一个半透明的activity阻塞activity时,系统会调用onPause()方法并且这个activity会停留在Paused 状态(1).
如果用户在这个activity还是在Paused 状态时回到这个activity,系统则会调用它的onResume() (2).
暂停Activity
当系统调用activity中的onPause(),从技术上讲,意味着activity仍然处于部分可见的状态.但更多时候意味着用户正在离开这个activity,并马上会进入Stopped state. 通常应该在onPause()回调方法里面做以下事情:
停止动画或者是其他正在运行的操作,那些都会导致CPU的浪费.
提交在用户离开时期待保存的内容(例如邮件草稿).
释放系统资源,例如broadcast receivers, sensors (比如GPS), 或者是其他任何会影响到电量的资源。
例如, 如果程序使用Camera,onPause()会是一个比较好的地方去做那些释放资源的操作。
@OverridepublicvoidonPause(){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()来保存用户改变的数据 (例如填入表格中的个人信息) 到永久存储(File或者DB)上。仅仅当确认用户期待那些改变能够被自动保存的时候(例如正在撰写邮件草稿),才把那些数据存到永久存储 。但是,我们应该避免在onPause()时执行CPU-intensive 的工作,例如写数据到DB,因为它会导致切换到下一个activity变得缓慢(应该把那些heavy-load的工作放到onStop()去做)。
如果activity实际上是要被Stop,那么我们应该为了切换的顺畅而减少在OnPause()方法里面的工作量。
Note:当activity处于暂停状态,Activity实例是驻留在内存中的,并且在activity 恢复的时候重新调用。我们不需要在恢复到Resumed状态的一系列回调方法中重新初始化组件。
恢复activity
当用户从Paused状态恢复activity时,系统会调用onResume()方法。
请注意,系统每次调用这个方法时,activity都处于前台,包括第一次创建的时候。所以,应该实现onResume()来初始化那些在onPause方法里面释放掉的组件,并执行那些activity每次进入Resumed
state都需要的初始化动作 (例如开始动画与初始化那些只有在获取用户焦点时才需要的组件)
下面的onResume()的例子是与上面的onPause()例子相对应的。
@OverridepublicvoidonResume(){super.onResume();// Always call the superclass method first// Get the Camera instance as the activity achieves full user focusif(mCamera ==null) { initializeCamera();// Local method to handle camera init}}
停止与重启Activity
停止activity
当activity调用onStop()方法, activity不再可见,并且应该释放那些不再需要的所有资源。一旦activity停止了,系统会在需要内存空间时摧毁它的实例(和栈结构有关,通常back操作会导致前一个activity被销毁)。极端情况下,系统会直接杀死我们的app进程,并不执行activity的onDestroy()回调方法, 因此我们需要使用onStop()来释放资源,从而避免内存泄漏。(这点需要注意)
尽管onPause()方法是在onStop()之前调用,我们应该使用onStop()来执行那些CPU intensive的shut-down操作,例如往数据库写信息。
例如,下面是一个在onStop()的方法里面保存笔记草稿到persistent storage的示例:
@OverrideprotectedvoidonStop(){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 =newContentValues(); 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对象会保存在内存中,并在activity resume时被重新调用。我们不需要在恢复到Resumed state状态前重新初始化那些被保存在内存中的组件。系统同样保存了每一个在布局中的视图的当前状态,如果用户在EditText组件中输入了text,它会被保存,因此不需要保存与恢复它。
Note:即使系统会在activity stop时停止这个activity,它仍然会保存View对象的状态(比如EditText中的文字) 到一个Bundle中,并且在用户返回这个activity时恢复它们(下一小节会介绍在activity销毁与重新建立时如何使用Bundle来保存其他数据的状态).
启动与重启activity
当activity从Stopped状态回到前台时,它会调用onRestart().系统再调用onStart()方法,onStart()方法会在每次activity可见时都会被调用。onRestart()方法则是只在activity从stopped状态恢复时才会被调用,因此我们可以使用它来执行一些特殊的恢复(restoration)工作,请注意之前是被stopped而不是destrory。
使用onRestart()来恢复activity状态是不太常见的,因此对于这个方法如何使用没有任何的guidelines。然而,因为onStop()方法应该做清除所有activity资源的操作,我们需要在重启activtiy时重新实例化那些被清除的资源,同样,
我们也需要在activity第一次创建时实例化那些资源。介于上面的原因,应该使用onStart()作为onStop()所对应方法。因为系统会在创建activity与从停止状态重启activity时都会调用onStart()。也就是说,我们在onStop里面做了哪些清除的操作,就该在onStart里面重新把那些清除掉的资源重新创建出来。
例如:因为用户很可能在回到这个activity之前已经过了很长一段时间,所以onStart()方法是一个比较好的地方来验证某些必须的系统特性是否可用。
@OverrideprotectedvoidonStart(){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 enabledLocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);booleangpsEnabled = 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"}}@OverrideprotectedvoidonRestart(){super.onRestart();// Always call the superclass method first// Activity being restarted from stopped state}
当系统Destory我们的activity,它会为activity调用onDestroy()方法。因为我们会在onStop方法里面做释放资源的操作,那么onDestory方法则是我们最后去清除那些可能导致内存泄漏的地方。因此需要确保那些线程都被destroyed并且所有的操作都被停止。
重新创建Activity
编写:kesenhoo- 原文:http://developer.android.com/training/basics/activity-lifecycle/recreating.html
有几个场景中,Activity是由于正常的程序行为而被Destory的。例如当用户点击返回按钮或者是Activity通过调用finish()来发出停止信号。系统也有可能会在Activity处于stop状态且长时间不被使用,或者是在前台activity需要更多系统资源的时关闭后台进程,以图获取更多的内存。
当Activity是因为用户点击Back按钮或者是activity通过调用finish()结束自己时,系统就丢失了对Activity实例的引用,因为这一行为意味着不再需要这个activity了。然而,如果因为系统资源紧张而导致Activity的Destory, 系统会在用户回到这个Activity时有这个Activity存在过的记录,系统会使用那些保存的记录数据(描述了当Activity被Destory时的状态)来重新创建一个新的Activity实例。那些被系统用来恢复之前状态而保存的数据被叫做 "instance state" ,它是一些存放在Bundle对象中的key-value pairs。(请注意这里的描述,这对理解onSaveInstanceState执行的时刻很重要)
Caution:你的Activity会在每次旋转屏幕时被destroyed与recreated。当屏幕改变方向时,系统会Destory与Recreate前台的activity,因为屏幕配置被改变,你的Activity可能需要加载另一些替代的资源(例如layout).
默认情况下, 系统使用 Bundle 实例来保存每一个View(视图)对象中的信息(例如输入EditText
中的文本内容)。因此,如果Activity被destroyed与recreated,
则layout的状态信息会自动恢复到之前的状态。然而,activity也许存在更多你想要恢复的状态信息,例如记录用户Progress的成员变量(member
variables)。
Note:为了使Android系统能够恢复Activity中的View的状态,每个View都必须有一个唯一ID,由android:id定义。
为了可以保存额外更多的数据到saved instance state。在Activity的生命周期里面存在一个额外的回调函数,你必须重写这个函数。该回调函数并没有在前面课程的图片示例中显示。这个方法是onSaveInstanceState(),当用户离开Activity时,系统会调用它。当系统调用这个函数时,系统会在Activity被异常Destory时传递 Bundle 对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的onRestoreInstanceState()方法与 onCreate() 方法中。
Figure 2.当系统开始停止Activity时,只有在Activity实例会需要重新创建的情况下才会调用到onSaveInstanceState()(1) ,在这个方法里面可以指定额外的状态数据到Bunde中。如果这个Activity被destroyed然后这个实例又需要被重新创建时,系统会传递在 (1) 中的状态数据到 onCreate() (2) 与onRestoreInstanceState()(3).
(通常来说,跳转到其他的activity或者是点击Home都会导致当前的activity执行onSaveInstanceState,因为这种情况下的activity都是有可能会被destory并且是需要保存状态以便后续恢复使用的,而从跳转的activity点击back回到前一个activity,那么跳转前的activity是执行退栈的操作,所以这种情况下是不会执行onSaveInstanceState的,因为这个activity不可能存在需要重建的操作)
保存Activity状态
当我们的activity开始Stop,系统会调用 onSaveInstanceState()
,Activity可以用键值对的集合来保存状态信息。这个方法会默认保存Activity视图的状态信息,如在 EditText 组件中的文本或
ListView 的滑动位置。
为了给Activity保存额外的状态信息,你必须实现onSaveInstanceState() 并增加key-value pairs到 Bundle 对象中,例如:
staticfinalString STATE_SCORE ="playerScore";staticfinalString STATE_LEVEL ="playerLevel";...@OverridepublicvoidonSaveInstanceState(Bundle savedInstanceState){// Save the user's current game statesavedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);// Always call the superclass so it can save the view hierarchy statesuper.onSaveInstanceState(savedInstanceState);}
Caution: 必须要调用 onSaveInstanceState() 方法的父类实现,这样默认的父类实现才能保存视图状态的信息。
恢复Activity状态
当Activity从Destory中重建,我们可以从系统传递的Activity的Bundle中恢复保存的状态。 onCreate() 与 onRestoreInstanceState() 回调方法都接收到了同样的Bundle,里面包含了同样的实例状态信息。
由于 onCreate() 方法会在第一次创建新的Activity实例与重新创建之前被Destory的实例时都被调用,我们必须在尝试读取
Bundle
对象前检测它是否为null。如果它为null,系统则是创建一个新的Activity实例,而不是恢复之前被Destory的Activity。
下面是一个示例:演示在onCreate方法里面恢复一些数据:
@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);// Always call the superclass first// Check whether we're recreating a previously destroyed instanceif(savedInstanceState !=null) {// Restore value of members from saved statemCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }else{// Probably initialize members with default values for a new instance} ...}
我们也可以选择实现 onRestoreInstanceState() ,而不是在onCreate方法里面恢复数据。
onRestoreInstanceState()方法会在 onStart() 方法之后执行. 系统仅仅会在存在需要恢复的状态信息时才会调用 onRestoreInstanceState() ,因此不需要检查 Bundle 是否为null。
publicvoidonRestoreInstanceState(Bundle savedInstanceState){// Always call the superclass so it can restore the view hierarchysuper.onRestoreInstanceState(savedInstanceState);// Restore state members from saved instancemCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);}
Caution: 与上面保存一样,总是需要调用onRestoreInstanceState()方法的父类实现,这样默认的父类实现才能保存视图状态的信息。更多关于运行时状态改变引起的recreate我们的activity。请参考Handling Runtime Changes.