Android四大组件之:Activity(官方介绍翻译)

官方原文:http://developer.android.com/guide/components/activities.html

转载请注明出处:http://blog.csdn.net/xiong_it/article/details/42556497。谢谢!

概述:


Activity是一个应用程序通过屏幕提供给用户进行交互界面的Android组件,比如打电话,拍照,发邮件,或者查看地图。每个Activity都有一个窗口,在上面绘制了程序的用户界面。这个窗口通常会占满整个屏幕,但是也可以比屏幕小,或者悬浮在其他窗口上。


一个程序一般会由多个Activity结合在一起。典型情况下,主Activity是当程序启动时首先呈现在用户眼前的Activity。每个Activity为了执行不同的行为都能跳转到其他任何一个Activity。当新的Activity 开启时,先前的那个Activity会停止,但是系统会保存前面那个Activity的状态在栈中。当新Activity 开启时,它会被放入回退栈中并获的用户的焦点。回退栈秉承“后进先出"的原则,所以,当用户在当前Activity按下返回键时,它会从回退栈中弹出并销毁,同时,前面那个Activity会重新获得用户焦点(想知道更多回退栈知识:http://developer.android.com/guide/components/tasks-and-back-stack.html)。


当一个Activity因为新Activity 开启而停止时,可以通过Activity的生命周期回调方法知道它的状态改变。有一些回调方法会在这个过程中被接收执行,因为状态无论如何改变--创建,停止,获得焦点的一个Activity,或者销毁一个Activity--每个回调方法都提供给开发者在Activity状态改变前做一些特定的操作的机会。比如说,当Activity停止时,Activity需要释放一些资源,像断开网络,数据库连接。当Activity得到焦点,你可以请求必要的资源和让被打断的操作重新执行。这些状态过渡就是Activity的所有生命周期。


本文的其余部分将讨论如何创建和使用Activity,包括Activity各个生命周期的工作原理的完整讨论,这样你就可以适当地管理Activity的状态之间的转换


创建Activity


创建一个自定义Activity时你必须继承Activity(或者继承一个已经集成Activity的基类),在你创建的Activity中,你需要实现Activity生命周期过渡时的回调方法,比如当这个Activity创建,停止,重新开始,或者销毁。其中两个最重要的回调方法是:

onCreate()

你必须实现这个方法。系统会在你创建Activity时调用这个方法。在你实现这个方法之前,你需要初始化Activity的核心组件。比如,你需要调用setContentView()来定义你的Activity用户界面的layout布局(以下简称布局)。

onPause()

系统会在用户离开这个Activity这个时刻调用这个方法(通常情况下,它不一定会被销毁)。在这个方法中,你可以保存一些需要维持的变化(以为用户可能还需要回到这个Activity)。


你需要使用这些生命周期的回调方法以便你能在不同的Activity之间切换提供一个流畅的用户体验,和处理一些因为切换而产生的异常导致你的Activity被停止甚至销毁。所有的生命周期回调方法都将在后面继续讨论,详情请参阅: Managing the Activity Lifecycle。


实现用户接口

一个Activity的用户界面由View类派生的view对象分层次结构提供。每个view都在Activity的窗口中控制了一个特定的矩形的空间,它们能够接收响应用户的交互操作。比如,一个按钮是一个view对象,当用户触摸它可以发起一个响应动作。


Android提供了许多现成的view对象,你可以用它们来设计和组织你的layout布局(以下简称布局)。"Widgets"是views提供给屏幕的可视化(和可交互的)元素,诸如按钮,文本字段,复选框,或者仅仅是显示一张图片等控件。“Layouts”是继承自ViewGroup的views,提供一个独一无二的布局容器给它的子view(笔者注:子view指的是放在ViewGroup中的控件),比如有线性布局Linear layout,网格布局Grid layout,以及相对布局Relative layout等。你也可以继承View或者ViewGroup类(或现有的子类)来自定义控件,布局和主题并应用到你的Activity。


定义视图布局最常用的方法是在你的应用程序资源目录下(笔者注:res/layout)保存设计好的XML布局文件。使用这个方法你可以保证设计用户界面和编写Activity行为的代码分离开。你可以Activity中使用setContentView()方法中指定布局文件的ID去设置你的用户界面,你也可以在Activity中使用代码new Views()插入到ViewGroup父视图控件容器(以下简称父视图控件容器)中来创建新的分层次结构的视图,然后通过传递对象根父视图控件容器到setContentView()中作为参数来替代布局文件

有关创建UI用户界面的信息,请参阅用户界面文档:http://developer.android.com/guide/topics/ui/index.html

在清单文件中声明Activity

为了系统能够知道这个Activity的存在你必须声明你写的每个Activity。打开清单文件,在<application>节点下添加<activity>节点,如下所示:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

在Activity节点下还有一些其他属性,比如label属性定义了一个代表特定Activity的图标,或者Activity的UI style的主题theme。android:name 属性是唯一必须的属性,它用来指定Activity的类名。一旦你发布了你的程序,你就不能再改变这个类名了,因为如果你改变的话,你可能会缺少一些功能,比如应用程序快捷方式(更多请看博客:Things That Cannot Change)。

查看在清单文件中声明<activity>节点引用的更多信息:http://developer.android.com/guide/topics/manifest/activity-element.html

使用 intent filters

一个<Activity>节点还可以使用<intent-filter>节点(笔者注:<意图过滤器>节点)来告诉应用程序的其他组件怎样才能激活它

当您使用Android SDK工具创建新的应用程序,会自动为您创建Activity的意图过滤器,它声明了Activity响应“main”的行为(笔者注:遵循原句翻译,实际意思为:它声明了Activity主要响应什么样的action),category类别会使用“launcher(笔者注:遵循原句翻译,实际意思为:它声明了Activity属于什么类别,默认为启动类型)。默认情况如下:

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>


<action>节点用来指定Activity的主入口行为,<category>指定了该Activity在应用程序中允许用户启动这个Activity。

如果您打算让您的Activity仅仅包含在自身应用程序中,而不允许其他应用程序来激活该Activity,那么你不需要添加任何意图过滤器。只有一个Activity应该具有“main”操作和“launcher”的范畴,如前面的例子中。你不想让其他应用程序的拥有特定Activity的启动意图时,你不必添加意图过滤器节点,这时,您可以使用显式意图的方式自己启动它们(Activity)(在下面的章节中讨论)。

但是,如果你想你的Activity响应其他应用程序(和应用程序本身的)提供隐含的意图,那么你必须为你的活动定义意图过滤器。对于每种类型的您要响应的意图,你必须包括<intent-filter>节点,其中包括一个<action>节点和一个可选的<category>节点或<data>节点。这些节点可以声明指定Activity可以响应的意图类型。

有关您的Activity如何响应意图的更多信息,请参阅意图和意图过滤器的文档:Intents and Intent Filters

开启Activity


你可以开始任何一个Activity通过调用startActivity()方法,并给它传递一个描述了你想开启的Activity的intent意图对象(以下简称意图对象)作为参数。意图对象指定了你想启动的Activity的类名或你想启动的Activity的action入口类型(系统会自动为你选择符合action的程序并呈现出来供你选择)。一个意图对象还可以携带当前Activity中的少量的数据传递到将要启动的Activity中。

当在自己的应用程序中进行操作,你经常需要简单地启动一个已知的活动。你可以通过创建明确规定要开始Activity的意图对象,例如,如何使用Activity类名从一个Activity启动另一个Activity(名SignInActivity):

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

然而,你的应用程序也可能需要使用你Activity中的数据执行一些操作,比如发送电子邮件,短信或状态更新。在这种情况下,你的应用程序可能没有自己的Activity来执行这样的操作,这时你可以使用当前设备上的其它应用程序的Activity来执行操作。这时意图的价值显现出来,你可以床架一个描述将要执行的操作的意图,系统从其他应用程序中启动具有对应意图的Activity,如果有多个程序能够执行你的操作,那么用户可以自由选择哪个程序去执行操作。例如你可以创建下面的意图让用户去发送一封e-mail:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);


额外添加到意图EXTRA_EMAIL是该邮件要发送电子邮件地址的字符串数组。当电子邮件应用程序响应这个意图,它读取额外提供的字符串数组,并把它们在电子邮件撰写表格的“到”字段中。在这种情况下,在电子邮件应用程序的活动开始,并在用户完成时,你的活动恢复。

额外添加到意图的是该邮件要发往电子邮件地址的字符串数组。当发送邮件的应用程序响应了这个意图时,它会读取额外提供的字符串数组,并把他们填写在电子邮件撰写表格的收件人地址处。在这种情况下,在电子邮件应用程序的Activity开启,并在用户完成发送邮件时时,你的Activity恢复。

开启一个带返回结果的Activity

有时,你可能需要从你将要启动的Activity的获取数据结果。这时,你可以使用startActivityForResult()(而不是startActivity())。为了从后续Activity中得到数据,当前Activity需要实现onActivityResult()这个回调方法。当随后的Activity完成后,它返回一个携带结果数据的意图对象到你的onActivityResult()方法中。


例如,也许你希望用户来选择一个他们的联系人,使你的Activity可以做一些与联系人信息的操作。你可以这样创建一个意图并处理返回的结果:

private void pickContact() {
    // Create an intent to "pick" a contact, as defined by the content provider URI</span><span style="font-size:14px;">
    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
        // Perform a query to the contact's content provider for the contact's name
        Cursor cursor = getContentResolver().query(data.getData(),
        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor.moveToFirst()) { // True if the cursor is not empty
            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
            String name = cursor.getString(columnIndex);
            // Do something with the selected contact's name...
        }
    }
}


这个例子主要是在onActivityResult()方法中使用一些简单的逻辑处理了返回的结果。首先,需要检查是否请求成功,如果成功返回的resultCode结果码等于RESULT_OK(笔者注:也即是-1),此时,返回结果中的requestCode如果等于startActivityForResult()的第二个参数(笔者注:第二个参数也即是发送请求的requestCode)。在这儿,你酒可以编写代码通过查询返回意图对象中的数据()来处理返回的结果了。

这儿使用了一个ContentResolver内容观察者对象执行了一个针对内容提供者的查询操作,它返回了一个游标对象用来查询允许读取的数据。欲了解更多信息,请参阅内容提供者的文档:http://developer.android.com/guide/topics/providers/content-providers.html

有关使用意图的更多信息,请参阅意图和意图过滤器的文档:http://developer.android.com/guide/components/intents-filters.html


结束Activity



你可以通过调用finish()方法来结束当前Activity。你也可以通过调用finishActivity()方法结束一个以前启动的单独的Activity。

注:在绝大多数情况下,你不需要使用这个方法去明确地去结束一个Activity。在以下部分将讨论Activity的有关生命周期,Android系统会为你自动管理Activity的生命周期,所以你不需要去结束自己的Activity。调用这个方法可能会在用户体验方面造成预料之外的负面效果,除非你确定你不希望用户再次返回到这个Activity对象当中。

管理Activity生命周期


如果你需要开发一个强大并且灵活的应用,学会通过实现回调方法来管理你的Activity生命周期是至关重要的。一个Activity的生命周期直接受到其他相关联的Activity,以及它的任务和回退栈的影响。

一个Activity有以下三种基本状态:

Resumed

此时Activity处于屏幕最上层,并拥有用户焦点。(该状态又被称为“运行”)

Paused

当前Activity另一个Activity占据屏幕上层和焦点,但当前Activity仍为可见状态,也就是说,另一个Activity在当前Activity的上层,当前Activity变成部分透明或者不覆盖整个屏幕。一个处于暂停状态的Activity是活的(会被保留在内存中,它保持了所有的状态和变量信息,并且仍然关联在windows manager上),但是会在系统内存吃紧的情况下被杀死。

Stopped

这个Activity被另一个Activity完全挡住了(这个Activity现在处于“后台运行”)。一个处于stop状态的Activity仍然是活着的(它会被保留在内存中,保持了所有的状态和变量信息,但是不关联在windows manager上)。然而,这个Activity现在不再可见,当任何其他地方需要内存时它都会被系统杀死。

如果Activity处于paused 或者stopped,系统可以调用(finish())方法或者干脆杀死自身进程把它从内存中清除。当这个Activity再次开启(在被杀死后),它必须完整的重新create一遍。


实现生命周期回调方法

当一个Activity的发生如上所述的状态变化,它都是通过各个毁掉方法得到通知,所有的回调方法就是钩子,当你的Activity状态变化时你可以重写相应回调方法做对应处理。下面的例子包括了Activity的每一个生命周期的基本方法(笔者注:其实还有onRestart()例子中没有提到,这是当Activity重启时在onStart()前执行的一个回调方法):

public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The activity is being created.
    }
    @Override
    protected void onStart() {
        super.onStart();
        // The activity is about to become visible.
    }
    @Override
    protected void onResume() {
        super.onResume();
        // The activity has become visible (it is now "resumed").
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be "paused").
    }
    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
    }
}

注:您执行这些生命周期方法在做任何工作前必须调用父类的实现(笔者注;即super.xx()),如上面的例子。

综合考虑,这些方法定义了Activity的整个生命周期。通过实现这些方法,你可以控制Activity生命周期中的三个嵌套循环:

Activity完整的生命状态发生在调用onCreate()和onDestroy()之间。你需要Activity的onCreate()方法中完成“全局”状态(比如定义布局)的操作,在onDestroy()方法中释放所有持有的资源。比如说,如果你的Activity有一个线程在后台下载网络数据,它可能在onCreate()方法中创建的,需要在onDestroy()方法中停止这个线程。

Activity可见的状态发生在调用onStart()和onStop()之间。在这期间,用户可以在屏幕上看见Activity并与之交互。比如,onStop()是一个Activity在一个新的Activity开启后不再可见的状态。在这两个方法之间,你要维护需要展示给用户的Activity上的数据资源。比如,你可以在onStart()中注册一个BroadcastReceiver广播接收者来监控更改你的UI变化的因素,当用户不再需要你展示的数据时,你可以在onStop()中注销这个广播接收者。系统在Activity整个生命周期中,在可见于隐藏状态之间切换的时候可能会多次调用onStart()和onStop()方法。

Activity的前台状态发生在调用onResume(),onPause()之间。在此期间,当前Activity处于所有Activity的上层,在屏幕上拥有用户的输入焦点。Activity会频繁的在前台和后台之间切换-比如,onPause()会在设备进入睡眠状态或dialog弹窗时调用。因为经常进入这个状态,所以这两个方法中的代码应尽量简单避免状态过渡缓慢而造成用户等待。

图1说明了这些生命周期和一个Activity状态之间切换可能的路径。矩形代表Activity状态切换时你可以实现的执行操作的回调方法

Activity生命周期图

图1.Activity生命周期

表1是列举了上图中同样的Activity生命周期回调方法,其中描述每个回调方法的细节和回调方法在Activity在整个生命周期的具体位置,包括在回调方法完成后系统是否可以杀死该Activity。

表1. Activity生命周期的回调方法总结表

方法描述可杀死与否接下来是
onCreate()在Activity第一次创建时调用。你需要在这里做所有的普通的静态设置-创建视图,取得数据并放进集合等等。这个方法参数中的bundle对象包含了Activity先前的状态信息,如果状态被保存了的话。
后面常跟onStart()
onStart()
onRestart()在Activity停止后,重新开始的时候调用。
后面常跟onStart()方法
onStart()
onStart()在Activity即将变为可见时调用。
常跟onResume()时Activity切换到前台,跟onStop()时Activity被隐藏
onResume()/
onStop()
onResume()在Activity开始和用户交互时调用。这时Activity位于Activity回退栈的顶端,用户可以进行输入等操作。
常跟onPause()
onPause()
onPause()在系统即将让另一个Activity获得焦点时调用。这个方法通常用来提交未保存的变化到可持续化数据中,停止动画以及可能消耗CPU的事情等操作。它做的操作需要迅速完成,因为即将获得覆盖它的Activity只能等到这个方法执行完才能获得焦点。
跟onResume()表示Activity重新获得焦点,跟onStop()表示它即将不可见。
onResume()/
onStop()
onStop()在Activity不再可见时调用。可能因为Activity被销毁,或者另一个Activity(已存在的或者新创建的)已经获得焦点并遮住了它。
跟onRestart()表示这个Activity又获得焦点进行交互,跟onDestroy()表示Activity即将被销毁
onRestart()/
onDestroy()
onDestroy()在Activity被销毁前调用。这个方法是Activity能够接收的最后一个方法。它可以在Activity正在结束的时候(有人在这个方法里调用finish()方法)或者因为系统正在暂时性销毁这个Activity的实例来节省内存空间时调用。你可以通过使用isFinishing()方法来分辨这两种情况。


“可杀死与否”指的是系统能否在这个方法结束后杀死该Activity所在的进程,在不执行Activity代码的情况下(笔者注:这句我自己也不大懂,请知道的朋友告诉我。原句:without executing another line of the activity's code)。三个方法都标记为了”是“:(onPause(),onStop(),onDestroy())。因为onPause()在这三个方法中首先执行,一旦Activity被创建,onPause()是在当前进程被杀死前保证能调用的最后一个方法-如果系统在紧急情况下需要恢复足够内存,之后onStop(),onDestroy()可能不会调用。因此,你应该使用onPause()来保存关键的持久化数据(比如用户编辑)。但是,在onPause()中你需要选择哪些信息必须要保存,因为在这个方法中的代码可能发生的任何阻塞都会延缓切换到下一个Activity的时间从而影响用户体验

在”可杀死与否“被标记为”否“的方法阻止了Activity所在线程在它们调用时被杀死。因此,在onPause()过渡到onResume()调用时Activity能被杀死。在下一次onPause()调用结束之前他将不会再一次被标记为”可杀死“。

注:表1中的”可杀死与否“并不严谨,因为在系统资源极端缺乏的情况下,它仍可能被系统杀死。Activity何时可能被杀死的更多信息请看:Processes and Threading 文档。

保存Activity状态

在此简单地介绍下在怎样管理Activity生命周期Activity处于paused或者stopped状态时,如何保存Activity的状态。当Activity处于paused或stopped时Activity对象仍然保存并活在在内存中-所有有关它的信息仍然是存在的。因此,用户在Activity内做的任何修改都仍然存在,所以当Activity回到前台时(即”resumes“时),所做的改变仍然在内存中。

然而,当系统破坏的活性以回收存储器,活动对象被破坏,所以其状态完好,系统不能简单地恢复它。相反,系统必须重新创建活动对象,如果用户导航回到它。然而,用户不知道,该系统被破坏的活性和重新创建它,并且因此,可能是期望的活性是完全一样了。在这种情况下,可以确保有关活动的状态,通过实施额外的回调方法,它允许你保存你的活动状态信息保存重要信息:的onSaveInstanceState()。

然而,当系统为了恢复足够内存销毁一个Activity时,这个Activity对象就销毁了,所以系统无法经重新恢复它的完整状态。因此,如果用户重新回到这个Activity,系统必须重新创建这个Activity对象。然而,用户并不知道系统何时会销毁或创建这个Activity,但是用户却希望回到Activity原来的样子。这时,你需要一个允许你保存Activity状态信息的回调方法来保存它:就是onSaveInstanceState()。

系统在Activity遭到销毁之前调用onSaveInstanceState()方法。系统会传递一个Bundle对象到这个方法参数中,bundle中你可以利用名-值对来保存状态信息,比如使用putString()或者putInt()等方法。如果在系统杀死了你的程序进程时用户返回到你的Activity,系统会重新创建Activity并传递刚才的Bundle对象到onCreate(),onRestoreInstanceState()方法参数中。使用以上方法,你能保存你的Activity状态到bundle中并从中恢复。如果没有保存状态信息,传递过来的bundle为null(当Activity第一次创建时)。

保存恢复Activity状态

图2.这两个方法,使Activity在状态完好的情况下重新得到用户焦点:一种是Activity被销毁,系统重新创建了Activity并恢复了它之前保存的状态,一种是Activity停止,之后重新取得焦点时保持完好的状态。(笔者注:左边路径是第一种情况,右边路径是第二种情况)

注:onSaveInstanceState()不一定在你的Activitiy销毁之前调用,因为有些情况下你并不需要保存状态(比如用户使用返回键离开你的Activity,因为用户明确要关闭当前Activity)。如果系统调用onSaveInstanceState(),它可能在onStop()或onPause()前调用。

但是,即使你什么也不做,不实现的onSaveInstanceState(),一些活动状态是由对的onSaveInstanceState Activity类的默认实现恢复()。具体来说,默认实现调用相应的onSaveInstanceState()方法中的布局,这使得每个视图提供应保存自己的信息每天查看。几乎是在Android框架每部件实现了这个方法,适当的,这样,任何可见更改UI会自动保存,当你的活动重新恢复。例如,所述的EditText部件保存由用户输入的任何文本和复选框插件保存不管是检查或没有。你所需要的唯一工作是提供一个唯一的ID(用android:id属性),你要保存其状态每个插件。如果一个部件不具有一个ID,则系统不能保存它的状态。

但是,即使你什么也不做,没有实现onSaveInstanceState(),一些Activity状态仍会被Activity类的默认实现onSaveInstanceState()保存(笔者注:这句根据原文翻译,我猜想原文的意思是没有实现方法的情况下默认执行super.onSaveInstanceState(outState))。具体来讲,默认的实现调用了布局中每个View对象对应的onSaveInstanceState(outState)方法,这个布局允许每个view提供自身需要保存的信息。几乎所有Androidframework 层的每个控件都恰当的实现了这个方法,以至于任何对于UI可见的变化都会自动保存和恢复当Activity需要重新创建的时候。比如,EditText控件能保存用户输入的文字,Checkbox控件能保存自己是否被选中。唯一的条件就是你为每个你想保存自身状态的控件分配唯一的ID(就是使用android:id属性)。如果一个控件没有ID,系统将无法保存它的状态。

尽管onSaveInstanceState因为()的默认实现能够保存Activity的UI有用信息,你仍然可能需要重写它来保存更多信息。比如,你可能需要保存Activity生命过程中发生变化的变量值(可能是UI中恢复了的变量值,但是在默认情况下,持有这些变量值的变量并没有恢复)。

注:你还可以在布局中通过设定android:saveEnabled属性值为"false"或者调用setSaveEnabled()方法来阻止一个view对象保存自身状态信息。通常,你不应该这样做,但是如果你想以其他方式来恢复UI状态的话你可能需要这么做。

因为onSaveInstanceState()的默认实现可以保存UI状态,如果你为了保存更多状态信息复写了这个方法,你应该在做其他操作前调用父类的实现super.onSaveInstanceState()。同样的道理,如果你复写onRestoreInstanceState()时应首先调用onRestoreInstanceState()的父类实现super.onRestoreInstanceState(),默认的实现能够恢复视图状态。

注:由于onSaveInstanceState()不一定被调用,你在这个方法中应该只用来记录Activity(UI状态)短暂的状态-你永远都不要用这个方法来保存持久化数据。但是,当用户离开Activity时你可以在onPause()中来保存持久化数据(譬如需要保存到数据库的数据)。

测试你的应用程序恢复自身状态能力的一个好方法是旋转屏幕,是屏幕方向变化。当屏幕改变时,系统会销毁并创建Activity,以加载可能适合现在屏幕配置(方向)的可选择的资源文件。因此,当Activity重建时完整的恢复自身状态是非常重要的,因为用户使用过程中经常会旋转屏幕。

处理配置变化

有些设备在运行时会发生配置改变(如屏幕方向,键盘可用性,语言)。当这些变化发生时,Android系统重建并运行Activity(系统依次调用onDestroy(),onCreate())。这样做的目的的是帮助应用程序通过加载可替代资源(如不同屏幕大小,方向的不同布局文件)适应新的配置

如果你能正确地设计自己的Activity来处理由于屏幕方向变化的重新启动并恢复如上所述的Activity状态,你的应用将更具弹性,以应对在Activity生命周期中的异常事件。 

处理这样的Activity重启,最好的办法是使用onSaveInstanceState使用()和onRestoreInstanceState()(或onCreate())保存和恢复Activity的状态,在前一节中已讨论。

有关如何处理发生在运行时配置更改的详细信息,请阅读指南:Handling Runtime Changes

协调多个Activity

从一个Activity启动另一个Activity,它们都经历了生命周期变化。第一个Activity暂停,然后停止(不过,它在后台仍然存在),另一个Activity被创建。如果数据保存到磁盘或其他地方,这些Activity共享这些数据,理解在第二个Activity创建前第一个Activity并没有完全的停止是很重要的。相反,第二个Activity的开启过程和第一个Activity停止的过程有部分是同时进行的。

生命周期回调方法的顺序是明确定义的,特别是当这两个Activity在相同的过程,当一个Activity在开启其他Activity。以下是操作时Activity A开启Acivity B发生的顺序:

  1. Activity A的onPause() 方法执行。
  2. Activity B的 onCreate()onStart(), 和 onResume() 方法依次执行。 (Activity B 现在拥有了用户焦点)
  3. 然后, 如果Activity A 不在屏幕上可见, 它的 onStop() 方法执行。

这种可预见的生命周期回调方法执行顺序可以让你很好的管理Activity切换时信息的传递。比如,如果你必须在第一个Activity停止时写入数据库以保证接下来的Activity可以读取它,那么你需要在onPause()方法中写入数据库而不是在onStop()中。


结束语

如果你看到了这里,说明你一定花了不少时间,可就是这半个小时一个小时看完的文章却花了我一周多的时间,才终于把这篇文章翻译完成,衷心的向翻译出一本本IT行业中脍炙人口的好书的大牛们致敬!由于我这是第一次,文中有些地方翻译比较生涩,鉴于笔者能力有限,这些地方是结合语义以及笔者对Activity的理解写成,两幅附图就没翻译了,相信大家能看懂的,如果有什么不理解的地方,还请留言,我定及时回复。如有笔误,还请各位朋友指正,十分感谢!
后续还会陆续推出Android四大组件的其他三大组件翻译,还望继续关注。谢谢!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值