Android -- Activity官方文档简译


主要内容来自官方文档:Activity


Activity


public class Activity
extendsContextThemeWrapperimplementsLayoutInflater.Factory2,Window.Callback,KeyEvent.Callback, View.OnCreateContextMenuListener, ComponentCallbacks2




Activity是一个用户能独立、专心处理的事物。几乎所有Activity都与用户交互,所以Activity类会通过调用setContentView(View)来创建一个可以用来放置你的UI的窗口。尽管Activity经常以全屏窗口的形式呈现给用户,但它们也有其他的使用方法:作为浮动窗口(通过一个设置了WindowIsFloating的主题)或者嵌入其他Activity中(使用ActivityGroup)。

这里有两个几乎所有Activity子类都会实现的方法:

  • onCreate(Bundle)是你初始化Activity的地方。最重要的,这里你经常会调用setContentView(int)并传入一个布局资源来定义你的UI,并且通过调用findViewById(int)得到UI中在编程时需要交互的组件。
  • onPause()是处理用户离开你Activity的地方。最重要的,所有用户行为导致产生的变化都应该在此节点提交(例如ContentProvider持有数据)。

为了使用Context.startActivity(),所有Activity类型都必须在包的AndroidManifest.xml中存在对应的声明。


Activity生命周期


系统中的Activity以Activity栈的形式管理。当一个新Activity被启动后,它会被放置在栈的顶部并成为正在运行的Activity -- 它之前的Activity在栈中总是处于它的下面,并且直到新Activity退出时,它才会重新返回到前台。


一个Activity实质上有四中状态:

  • 如果一个Activity位于屏幕的最前面,它是active的或是running的
  • 如果一个Activity已经失去焦点,但是依然可见,那它是paused的。一个暂停的Activity还是完全存活的(它保留着所有状态和成员信息,并且仍然和window manager关联),但是在内存极端底的情况下,它可以被系统杀死。
  • 如果一个Activity完全被其他Activity隐藏,那它是stopped的。它仍然保留着所有状态和成员信息。由于它对用户不再可见,所以它的窗口是隐藏的,并且它可以在系统需要内存的任何时间点被杀死。
  • 如果一个Activity是stopped或是paused的,那么系统可以通过使它finish或者直接杀掉它的进程来丢弃它以获得内存。当再次被呈现给用户时,它必须被完全重启并恢复到之前的状态。

接下来的图展示了一个Activity的重要的状态路径图:




其中有三个关键的回路,我们在监测自己的Activity也许会感兴趣:

  • 一个Activity的完整生命周期发生在第一次调用onCreate(Bundle)和最终唯一一次调用onDestroy()之间。Activity应该在onCreate()中处理所有的全局初始化,并在onDestroy()中释放所有持有的资源。例如,假设有一个线程在后台通过网络下载数据,那么应在onCreate()中创建该线程,并在onDestroy()中停止它。
  • 一个Activity的可见生命周期发生在onStart()和onStop()调用之间。在这期间,用户可以在屏幕上看到该Activity,但它不一定在前台并和用户交互。在onStart()和onStop(0之间,我们可以继续持有那些要在Activity展现给用户时需要的资源。例如,你可以在onStart()中注册一个BroadcastReceiver来监听那些影响你UI的外界变化,并当用户无法再看到你展现的内容时在onStop()中注销它。onStart()和onStop()方法可以被多次调用,正如Activity对用户变换为可见和隐藏一样。
  • 一个Activity的前台(foreground )生命周期发送在onResume()和onPause()调用之间。这期间,Activity处在所有所有其他Activity之前,并和用户交互。一个Activity可以频繁地在resumed和paused状态之间转换;例如,当设备进入休眠,或者某个Activity result被抛出,或者一个新Intent被抛出时 -- 所以这些方法中应尽量只包含轻量级的代码。

接下来的Activity接口定义了一个Activity的完整生命周期。它们是一组“钩子”接口,你可以覆写它们,以便在Activity改变状态时做一些相应的工作。所有的Activity都会实现onCreate(Bundle)来完成它们的初始化步骤。许多Activity也会实现onPause()方法来提交变化的数据或者做一些工作以准备停止和用户交互。在实现这些方法时,你总是需要先调用父类中的该同名方法。

 public class Activity extends ApplicationContext {     protected void onCreate(Bundle savedInstanceState);     protected void onStart();     protected void onRestart();     protected void onResume();     protected void onPause();     protected void onStop();     protected void onDestroy(); }

通常情况下,贯穿Activity生命周期的一个回调转移过程如下所示:


Method Description Killable? Next
onCreate() Activity第一创建时调用。我们应该在该函数中做一般的初始化工作,如创建各个View对象、为列表绑定数据等。如果有的话,这个方法总是会提供你一个包含之前Activity冻结状态的Bundle对象。onStart()方法总是在该方法之后。 No onStart()
  onRestart() 在Activity停止之后,重新启动之前被调用。它之后总是调用onStart()方法。 No onStart()
onStart() 在Activity即将对用户可见时调用。如果Activity即将前台显著位置,那它之后是onResume()方法;如果Activity被隐藏,那它之后是onStop()方法。 No onResume() or onStop()
  onResume() 当Activity即将开始和用户交互时,它会被调用。此时,你的Activity会在栈的最顶端,用户可以对它进行输入操作。它之后总是onPause()调用。 No onPause()
onPause() 当系统开始(esume一个之前的Activity时,它会被调用。典型的,我们一般在此执行保存数据、关闭动画或其他某些消耗CPU资源的动作。该方法的执行必须非常快速,因为下一个Activity只会在该方法完成并返回后,才会被resume。如果Activity接下来返回到屏幕前台,那么它接下来是onResume()方法;如果Activity变成对用户不可见,那它之后是onStop()方法。 Pre-HONEYCOMB onResume() or
onStop()
onStop() 当一个Activity不再对用户可见时,该方法会被调用;因为另一个Activity会被resume并覆盖到它之上。这个方法也会在当一个Activity正在被启动,但此时另一个存在的Activity被直接处理到它之前,或者这个Activity即将被销毁时调用。如果一个Activity即将重新回到前台与用户交互,那它之后是onRestart()调用;如果这个Activity即将被销毁,那它之后是onDestroy()调用。 Yes onRestart() or
onDestroy()
onDestroy() 这是你的Activity在销毁之前,你能接收到的最后一个函数调用。当用户调用finish(),或者系统为了节省空间,需要暂时销毁该Activity实例时,你的Activity才会被销毁。你可以通过isFinishing()方法来区分这两种场景。 Yes nothing


注意表中的“Killable”一栏 -- 对于那些被标记为“killable”的方法,在这些方法返回之后,持有该Activity的进程可能会在不执行任何其他一行该Activity的代码的情况下被系统杀死。因此,你需要在onPause()中保存任何修改过的并需要保存的数据。除此之外,onSaveInstanceState(Bundle)会在该Activity转变成后台状态之前被调用,这允许你在给定的Bundle中,保存任何你Activity中的动态实例状态信息;之后当该Activity需要再次被创建时,你可以在onCreate(Bundle)中重新接收它们。我们需要注意的一点是,我们应该在onPause(),而不是onSaveInstanceState(Bundle)中,保存那些持久性数据;因为后者并不是生命周期回调的一部分,所以它并不会在文档中描述的每一个场景中都被调用。


对于那些没有被标记为“killable”的方法,Activity所在的进程在该方法调用开始并在它返回之后,都不会被系统杀死。因此,举个例子:一个Activity在onPause()之后,onResume()调用之前,它都处于进程可被杀死的状态。


启动Activity并获取结果


startActivity(Intent)方法可以用来启动Activity,它将会被放置在Activity栈的顶端。方法只需要一个Intent参数,它描述了需要被执行的Activity。


有时候你会想要从一个结束的Activity中得到一个返回结果。例如,你会开启一个Activity让用户从联系人列表中选择一个人;当该Activity结束时,让它返回被选中的结果。为了实现这种情况,你需要调用startActivityForResult(Intent, int)版本,它附带了一个定义此次调用请求的int型参数。该调用结果会通过onActivityResult(int, int, Intent)方法返回。


当一个Activity退出时,它可以调用setResult(int)向它的父Activity返回数据。它必须总是提供一个结果码,这可以是标准定义结果码 RESULT_CANCEELD/RESULT_OK,或者任何从RESULT_FIRST_USER开始的客户值。除此之外,这个Activity可以随意返回一个包含任何它期望的数据的Intent给父Activity。所有的这些信息都会在父Activity的onActivityResult()函数中出现,同时它也会附带之前提供的对此次调用的请求码。


如果子Activity由于诸如崩溃的原因运行失败了,它的父Activity将会收到一个带有RESULT_CANCELED码值的结果。

public class MyActivity extends Activity {     ...     static final int PICK_CONTACT_REQUEST = 0;     public boolean onKeyDown(int keyCode, KeyEvent event) {         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {             // When the user center presses, let them pick a contact.             startActivityForResult(                 new Intent(Intent.ACTION_PICK,                 new Uri("content://contacts")),                 PICK_CONTACT_REQUEST);            return true;         }         return false;     }     protected void onActivityResult(int requestCode, int resultCode,             Intent data) {         if (requestCode == PICK_CONTACT_REQUEST) {             if (resultCode == RESULT_OK) {                 // A contact was picked.  Here we will just display it                 // to the user.                 startActivity(new Intent(Intent.ACTION_VIEW, data));             }         }     } }


进程生命周期


Android系统会尝试尽可能地保存应用程序进程,但是当系统内存很低时,它最终也会去移除一些老的进程。正如Activity生命周期部分所描述的,决定移除哪一个进程跟用户与进程的交互状态密切相关。一般情况下,基于运行其中的Activity,一个进程可以有4种状态,下面以重要性为序列出。系统会按重要性从低(最后一个)到高(第一个)的顺序杀死应用进程。

  1. 前台Activity(处在屏幕顶端并与用户交互的Activity)被认为是最重要的。如果它使用的内存超过了设备上可获取的最大值,那么它的进程会在万不得已的情况下被杀死。通常情况下,此时设备已经达到了内存分页状态,所以它需要按序保持用户接口可响应。
  2. 一个可见的Activity(对用户可见但不处于前台状态)也是非常重要的,除非到了需要杀死它来维持前台Activity运行的地步,一般情况下,系统都不会去制裁它。
  3. 一个后台Activity(不在对用户可见并处于paused状态)的状态不再是危险的了,所以为了给其他前台或可见的进程回收内存,系统可以安全地杀死它所属的进程。如果它的进程将要被杀死,当用户操作并返回到它这个Activity时,它的onCreate(Bundle)函数将被调用,并且之前在它的onSaveInstanceState(Bundle)中提供的savedInstanceState信息也会被接收到;所以它可以将自己重启到之前的状态,就如用户离开它时的那样。
  4. 没有运行任何Activity或其他应用组件(如Service或BroadcastReceiver)的进程是一个空进程。当系统内存变低的时候,它们很快会被系统杀死。基于这点,你的任何在Activity之外运行的后台操作都需要在一个BroadcastReceiver或Service中执行,以确保系统知道它需要保持你的这个进程。


1、startActivityForResult(Intent intent, int resquestCode, Bundle options)


启动一个当它结束时你期望从它得到一个返回结果的Activity。当启动的Activity退出时,你的onActivityResult()方法会附requestCode参数被调用。如果你调用时使用的requestCode是负值,那它效果等同于startActivity(Intent)。


需要注意的是,该方法只有当你使用被定义成会返回结果的Intent协议时才应当被使用。在其他协议中(如ACTION_MAIN或者ACTION_VIEW),你也许并不会如期望地那样得到一个结果。如果你启动Activity时使用了FLAG_ACTIVITY_NEW_TASK标志,那么它将不会运行在你当前的Activity栈中,你会立即收到一个CANCELED结果。


作为一个特殊的例子,如果你在Activity的onCreate()/onResume()方法中,使用了一个大于等于0的requestCode参数去调用startActivityForResult();此时你的窗口只会在从启动的Activity中得到一个结果之后,它才会显示出来。这样可以避免当重定向到其他Activity时,屏幕会产生可见的闪烁。


Parameters
intent Intent: The intent to start.
requestCode int: If >= 0, this code will be returned in onActivityResult() when the activity exits.
options Bundle: Additional options for how the Activity should be started. See startActivity(Intent, Bundle) Context.startActivity(Intent, Bundle)} for more details.

This value may be null.


该函数一般与setResult(int requestCode, Intent data)结合使用。


2、onSaveInstanceState(Bundle outState)


用来得到一个Activity被杀死之前的某些状态,确保在该Activity被重新启动时,在onCreate(Bundle)/onRestoreInstanceState(Bundle)中,它可以根据Bundle中的信息重新恢复到被杀死之前的状态(Bundle对象通常会被同时传递给这两个方法)。


这个方法一般在某个Activity即将被杀死之前调用,所以将来当它重新回归时,它可以恢复它之前的状态。例如,Activity B被启动,并处在Activity A的前面,某个时间点为了回收资源,Activity A被杀死了;Activity会有一个通过该方法保存当前它的用户接口当前状态的机会,所以当用户重新返回到Activity A时,它的用户接口状态可以通过onCreate(Bundle)/onRestoreInstanceState(Bundle)接口重新得到恢复。


不要对该方法和Activity生命周期回调函数产生困惑(如onPause(),它总是在Activity被转入后台或即将被销毁时调用;如onStop(),总是在Activity销毁之前调用)。一个onPause()、onStop()方法会被调用,而onSaveInstanceState(Bundle)不会被调用的例子就是:用户手动将Activity A操作到Activity B之前;此时没有必要在Activity B上调用onSaveInstanceState()函数,因为此时没有需要保存的特定信息,所以系统就会避免去调用它。一个onPause()被调用,而onSaveInstanceState()不会的场景就是Activity B被启动,并且运行在Activity A之前;如果Activity A在Activity B的生命周期内没有被系统杀死,那么它的onSaveInstanceState()不会被调用,因为Activity A此时的用户接口状态并不会改变。


如果onSaveInstanceState()被调用,那么它会发生在onStop()之前。我们无法保证它的调用是否会发生在onPause()之前或之后。


3、onRestoreInstanceState(Bundle saveInstanceState)


当一个Activity被重新初始化为之前的状态时(saveInstanceState提供),它会在onStart()之后被调用。大多数时候,我们会简单实现onCreate(Bundel)来恢复Activity的状态;但有些时候在所有初始化工作都完成后,再在该函数中进行状态恢复,或者允许子类自己决定如何使用函数的默认实现,都是很方便的。该函数的默认实现就是将Activity的任何View状态恢复到之前onSaveInstanceState(Bundle)被调用时这些View最后冻结的状态那样。


该函数在onStart()和onPostCreate(Bundle)之间被调用。


更多相关文章

  1. android TelephonyManager
  2. android音频播放简单示例
  3. Android(安卓)状态栏透明和图标反色
  4. android中shape的使用(android:angle小解)
  5. android 调用webservice
  6. android gps开发必备资料(含测试demo下载)
  7. Android(安卓)用户界面【level 1】
  8. 三步搞定:Vue.js调用Android原生操作
  9. android API之KeyguardManager简介

随机推荐

  1. Android 显示系统 --- Surface Flinger
  2. android 应用开发:android studio使用笔记
  3. Android(安卓)提升开发效率工具(Template
  4. Android(安卓)Unique Device ID
  5. 下半年我想做的事
  6. Android OpenGl展示视频内容
  7. android 编译模块
  8. Android音量系统分析
  9. android 采集PCM音频数据并播放(支持USB
  10. [整理]android中几种常见的尺寸