安卓翻译—Activies

来源:互联网 发布:师傅弟子知错 编辑:程序博客网 时间:2024/04/29 07:21

一个Activity是提供用户交互的界面来做某些事情得一个应用组件,例如打电话,照片,发送邮件,或者看地图。每个activity都被给出一个窗口来刻画用户接口。这个窗口一般都是填充了整个屏幕,但是也可能会比屏幕更小,浮动与其它窗口的顶部。

一个应用经常是由几个宽松地绑定在一起的几个activities组成的。一般来说,应用中的一个activity被指定作为‘main’activity,当打开应用的时候首先呈现个用户。每个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的用户界面布局的地方。

onPause():

系统调用这个函数来作为用户离开activity的指示(尽管这不总意味着activity被销毁掉)。(后面的翻译不过来)

你应该还需要用到几种其它的生存循环回收函数来提供一个流畅的用户体验,在activities和处理意外的引起activity停止甚至销毁的中断之间。


实现用户界面

views的层级提供了activity的用户界面——由View 类衍生的对象。每个视图都控制着在activity中的一个特定的矩形区域,并且能对用户的交互做出反应。例如,一个视图可能是一个按钮,当用户触摸的时候启动一个行为。

安卓提供了一些已经准备好的视图使你能够用来设计和组织你的布局。“widgets”是能够给屏幕提供可视的(还有交互式的)元素,例如,按钮,复选框,或者仅仅是张图片。

laylouts是来源于视图组的视图,视图组为它的子类提供一个独一无二的布局类型,例如,线性布局,表格布局,或者相对布局。你也能够将View和ViewGroup划入子集来创建自己的小部件和布局,并也将它们应用到activity布局中。

用视图定义一个布局最常用的方式是在应用资源中包含进一个XML布局文件。这种方式下,你能够将用户界面的设计维护与定义activity的行为的源代码相分离。你能够通过使用setContentView()来设置布局的UI,为布局传递资源ID。然而,你也能够在你的activity代码中创建新的视图,和通过向ViewGroup中插入新View来建立新的视图金字塔,然后通过将根视图组传递给setContentView()来使用那个layout。

在manifest中声明activity

你必须在manifest文件中声明activity为了使系统能够获取它。声明activity时,打开manifest文件,在其中增加一个<activity>作为<application>标签的子元素。例如:

<manifest ... >  <application ... >      <activity android:name=".ExampleActivity" />      ...  </application ... >  ...</manifest >
这里也有几个其他的属性是你可以包含进这个标签里的,为了定义activity像这样的特性,label,icon,或者一个来设计activityUI的主题。android:name属性是唯一被要求的属性——它指定了activity的类名。一旦发布了应用,你就不能更改它的名字了,因为如果你这样做的话,你可能会破坏一些功能,例如应用的快捷方式。


使用intent过滤器

<activity>标签也能指定不同的intent过滤器——使用<intent-filter>标签——为了声明其它应用组件怎样可能激活它。

当你用Android SDK工具去创建一个新应用的时候,这个工具为你创建的根activity会自动包含进一个intent过滤器,声明activity对“main”行为做出回应,并且应该放置一个“launcher”分类。intent过滤器看起来像这样:

<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>标签指明了这是指向应用的主入口。<category>标签指明了这个activity应该被放置在系统应用启动器里(为了允许用户启动这个activity)。

如果你打算将你的应用独立,并且不允许其他应用激活它的activity,那么你不需要任何其它的intent过滤器。仅仅有一个activity有'main"行为和"launcher"分类,就如前一个例子中的一样。你打算对其它应用隐藏的activity应该没有intent过滤器,你可以用明确的intents来启动它们(下面的章节将要讨论)。

然而,如果你想让你的activity对由其它应用发出的模糊的intent做出回应,那么你必须为你的activity定义额外的intent过滤器。对每种你想要做出响应的intent,就必须包含一个里面包含有<action>标签的<intent-filter>,可选的有一个<category>或者一个<data>标签。这些标签指明了你的activity能够响应的intent类型。


启动一个Activity

你能够通过调用startActivity()来启动其它的activity,给它传递一个描述你想要启动的activity类型的intent。这个intent指明了你想要启动的特定的activity或者描述了想要执行的行为类型(系统为你选择合适的activity,甚至能够从不同的应用中选择)。一个intent也能携带微量的能够要启动的activity使用的数据。

Intent intent = new Intent(this, SignInActivity.class);startActivity(intent);
然而,你的应用也可能想要执行一些行为,例如,发送邮件,短信,或者状态更新,使用从activity中来的数据。在这种情况下,你的应用可能没有执行这种行为的activity,因此你能利用设备上其他能够执行这种动作的activity来代替。这就是intent的价值所在——你能够创建一个intent来描述想要执行的动作,然后系统会从其它的应用中来启动合适的activity。如果这里有多个能够处理intent的activity,那么用户可以选择一个来使用。例如,如果你想允许用户发送一封邮件,你能够创建一个类似下面的intent:

Intent intent = new Intent(Intent.ACTION_SEND);intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);startActivity(intent);
额外加进intent的EXTRA_EMAIL是邮件应该发送地方的地址的字符串。当一个应用对这个intent做出响应,它会读取在extra中的字符串并将它放到邮件收件人的那一栏。在这种情况下,邮件应用的activity启动并且当用户使用完毕后,你的activity会恢复。


启动有反馈的activity

有时,你可能想从你启动的activity中得到一个结果。在那种情况下,通过调用startActivityResult()(代替startActivity())来启动activity。为了接收从后来的activity中的结果,需要实现onActivityResult()回收方法。当后来的activity结束后,它会在Intent中返回一个结果给你的onActivityResult()方法。

例如,你也许想让用户选取通讯录中的一个,因此你的activity需要对通讯录中的信息做些工作。这儿是你怎样能创建一个这样的intent和处理结果:

private void pickContact() {    // Create an intent to "pick" a contact, as defined by the content provider URI    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);    startActivityForResult(intent, PICK_CONTACT_REQUEST);}@Overrideprotected 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()方法中应该使用的基本逻辑来处理activity结果。第一个参数检查了请求是否成功——如果成功,resultCode值为RESULT_OK——不论结果正在响应的请求是否已知——在这种情况下,requestCode与startActivityForResult()的第二个参数相匹配。从这里,代码处理通过查询Intent中返回的数据来处理activity结果(数据参数)。

期间发生的是,ContentResolver执行一次查询通过content provider,然后返回一个允许数据被读取的游标(, which returns a Cursor that allows the queried data to be read.)。


关闭一个Activity

你能通过调用它的finish()方法来关闭它。你也能通过调用finishActivity()来关闭你之前启动的一个分离的activity。

注意:在大部分情况下,你不应该使用这些方法来结束一个activity。就如在下面的章节中讨论的关于activity生命循环的章节中,安卓系统为你来管理activity的生命,因此你不需要结束你的activity。调用这些方法,可能会不好地影响预期的用户体验,仅仅在你绝对不想让用户返回到这个activity实例上才使用它们。


管理activity生命循环

通过实现回收函数来管理activity的生命循环对开发一个强壮灵活的应用来说是重要的。activity的生命周期是被它与其它的activities,它的任务和返回栈直接影响的。

一个activity能在另外的三种状态下生存:

恢复:

activity在屏幕的最上方并且有用户焦点(这个状态在有时候也归做运行时)。

暂停:

另外一个activity在最前面并且有用户焦点,但是这一个仍然可视。这是,另外的activity在这个的最上面可视,并且那个activity部分透明或者没有覆盖全部屏幕。一个被暂停了的activity是确确实实地活着(Activity对象保存在记忆中,它维持着所有的状态和成员信息,依然依附于窗口管理器),但是在极端的低内存情况下会被杀死。

停止:

activity被另外的activity完全掩盖(activity现在是在后台)。一个停止了的activity是依然存在的(Activity对象保存在内存中,它保留着所有状态和成员信息,但是不依附于窗口管理器)。然而,它不再对用户可见,并且当内存需要用在其它地方的时候它会被杀死。

如果一个activity被暂停或者停止,系统能够通过请求它结束(调用它的finis()方法)或者仅仅杀死它的进程来将它从内存中取出。当activity被重新打开(在被结束后或者杀死后),它必须重新创建一遍。


实现生命周期回调函数

当一个activity转换成并且不是上面所述的状态,它会被各种回调函数通知。所有的回调函数都是当activity状态时你能够重写来做合适工作的挂钩。接下来的简要activity包含了每个基本的生命周期方法:

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.    }}
注意:你的这些生命周期方法的实现必须总是调用超类实现在做任何工作之前,就如上面的例子中展示的。


合起来,这些方法定义了一个activity的所有生命周期。通过实现这些方法,你能够在activity生命周期中监控三个嵌套的循环:

 activity的整个生命发生在对onCreate()和onDestory()的调用之间。你的activity应该在onCreate()中执行全局状态的设置(例如定义布局),和释放所有保存的资源在onDestory()中。例如,如果你的activity有一个线程运行在后台从网络中下载数据,它可能在onCreate()中创建那个线程,然后在onDestory()中停止线程。

activity的可见生命发生在onStart()和onStop()的调用之间。在这个时段内,用户能在屏幕上看到activity,还能与之交互。例如,onStop()当一个新的activity启动时被调用,

这个就不再可见。在这两个方法之间,你能够保存这些需要将activity展示给用户看的资源。例如,你能在onStart()中注册一个BroadcastReceiver来监控影像UI的变化,在onStop()中注销它当用户不再看你呈现的时候。系统可能会在activity的整个生命周期中调用onStart()和onStop()多次,因为activity可以在对用户可见和隐藏之间选择。

activity的前台生命发生在onResume()和onPause()的调用之间。在这个时段内,这个activity在屏幕上其它的activities之前,并且有用户的输入焦点。一个activity能平凡地转换成和转出前台——例如,onPause()当设备休眠或者当一个对话框出现时被调用。因为这个状态能经常转换,在这两个方法中的代码应该尽量的少来为了避免缓慢的转换时用户等待。



标签为“使用后是否能杀死”的列指明了系统是否能杀死正在托管activity的进程在方法返回之后的任意时间内,不再执行activity的代码。三个方法标记为 是:(onPause(),onStop(),onDestory())。因为onPause()是三个方法中的第一个,一旦activity被创建,onPasue()是在进程被杀死之前的保证被调用的最后一个方法——如果系统必须在紧急情况下恢复内存,那么onStop 和 onDestory()可能没被调用。因此,你应该用onPause()来将重要的永久数据(例如,用户编辑)存储起来。然而,你应该有选择性的保存信息,在onPause(),因为在这个方法任何阻塞的程序可能阻塞向下一个activity的转变和变慢用户体验。

在可被杀死的那一列标记为 NO的方法避免在它们被调用的时候沙溪正在托管activity的进程。因此,一个activity在从onPause()返回到onResume()的时间段内是可被杀死的。直到onPause()被再次调用和返回的时候是不可被杀死的。

注意:在表一中没有被标记为可杀死的activity仍然可被系统杀死——但是这仅发生在极端的没有其他援助的情况下。当一个activity可被杀死的时候的会在 Processes and Threading中讨论。


保存activity状态

管理activity生命周期的介绍明确地提到了当一个activity被暂停或者停止的时候,activity的状态是被保存的。这是真的,因为activity对象仍然存在于内存中当它被暂停或停止的时候——所有关于它的成员的信息和当前状态是仍然存在的。因此,任何用户对activity做出的变化被保留着以至于当activity返回到前台的时候(当它恢复的时候),这些变化仍然原封不动。


然而,当系统为了恢复内存销毁一个activity时,activity对象也被销毁掉,因此系统不能简单地恢复它原先的状态。相反,系统必须重新创建activity对象如果用户导航返回到它的时。用于缺意识不到系统销毁了它又重新创建了它,因此可能期望activity还是原先的样子。在这种情况下,你能确保关于activity状态的重要信息通过实现一个附加的回收函数保存,这个方法允许你保存关于你的activity状态的信息:onSaveInstanceState()。

系统调用onSaveInstanceState()在确认activity可被销毁之前。系统传递一个Bundle给这个方法,你能使用类似putString()和inPut()的方法来以名称—值对的方式来保存关于activity的状态信息。然后,如果系统杀死你的应用进程,用户导航会你的activity,系统重新创建activity并且将Bundle传递给onCreate()和onRestoreInstanceState()。使用这些方法中的一个,你能够从Bundle中提取保存的状态,重新存储activity状态。如果没有新的状态信息要存储,那么Bundle给你传递null值(当activity第一次被创建的情况)。

注意:onSaveInstanceState()在activity被销毁前被调用是不确定的,因为也有它不需要保存信息的情况(例如,当用户使用返回键的时候,因为用户很明确地关闭了activity)。如果系统调用了onSaveInstanceState(),它发生在onStop()之前和可能发生在onPause()之前。


然而,即使你不做任何事情并且不实现onSaveInstanceState(),activity的一些状态会被activity类的默认onSaveInstanceState()实现来保存。特别的是,默认实现调用为了在布局里的每个视图调用类似的onSaveInstanceState()方法,这样允许每个视图提供关于它自己应该保存的信息。几乎在安卓框架中的每个小部件都是合适地实现了这个方法,一次任何可见的UI改变都自动地保存和存储当activity被重新创建的时候。例如,EditText小部件保存了用户输入的任何文本,复选框小部件保存了它是否被选择过。你需要做的唯一工作是为每个你想保存的状态的小部件提供一个独一无二的ID(使用android:id)。如果一个小部件没有ID,那么系统不能保存它的状态。


尽管onSaveInstanceState()的默认实现保存了关于关于你activity UI的有用信息,你仍然可能需要重载它来保存额外的信息。例如,你可能需要保存改变的成员值在activity的生命期间(可能重新保存在UI中的值相关,但是成员持有的那些UI值不被重新保存,默认情况下)。


因为onSaveInstanceState()的默认实现帮助保存UI的状态,如果你重载这个方法为了保存额外信息,你应该总是在做任何工作前来调用onSaveInstanceState()的超类。同样地,如果你重载它的话,你也应该调用onSaveInstanceState()的超类实现,因此默认实现能重新保存视图状态 。

注意:因为onSaveInstanceState()不一定会被调用,你应该使用它仅仅记录activity短暂的状态(UI的状态)——你应该从来不用它保存永久数据。相反,你应该用onPause()来保存持久数据(像应该保存在数据库中的数据)当用户离开activity的时候。

一个测试我们的应用重新保存它的状态的能力好的方式是简单地旋转设备,这样屏幕的方向就改变了。当屏幕方向改变时,系统会摧毁和重新创建activity来为新的屏幕配置应用可能存在的可选择的资源。除了这个原因,当activity被重新创建时,它重新存储它的状态是非常重要的,因为用户当使用应用时经常转动屏幕。


处理配置改变

一些设备的配置能在运行时改变(例如屏幕方向,键盘可用性,和语言)。当类似的改变发生时,安卓重新创建正在运行的activity(系统调用onDestory(),然后直接调用onCreate())。这个行为被设计出来为了帮助应用采用新的配置,通过用你提供的可选择的资源来自动重新装载应用(例如,不同的布局对不同屏幕方向和尺寸)。


如果你正确地设计activity处理因为屏幕改变的的重新开始,并且重新存储像上面所描述的activity状态,你的应用将会相对于其他在activity生命周期中意料之外的事件更有弹性。


处理想这样的重新开始的最好的方式是使用onSaveInstanceState()和onStoreInstanceState()(或者onCreate())保存和重新存储你的activity的状态,像之前章节中讨论的。


协调的activity

当一个activity启动另外一个时,它们两个都经历了生命周期转换。第一个activity暂停和停止(但是,如果它在前台依然可见就不会停止),然而另外一个activity被创建。在这些activity共享保存在硬盘或者其它地方上的数据时,理解第一个activity在第二个被创建前没有完全停止是非常重要的。当然啦,启动第二个activity的进程重叠了停止第一个activity的进程。


生命周期回调的顺序是被定义好了的,特别是当两个activity在同一个进程并且一个正在启动另外一个。这里是当Activity A启动Activity B时发生的操作顺序:

1. Activity A的onPause()方法执行。

2. Activity B 的onCreate(),onStart(),onResume方法顺序执行。(Activity B 现在有着用户焦点)

3.然后,如果Activity A不再屏幕上可见,它的onStop()方法执行。

这些可预料的生命周期回调允许你管理从一个activity到另外一个过渡信息。例如,如果当第一个activity停止的时你必须写入数据库以便后面的activity能够读取它,那么你应该在onPause()期间写入数据库而不是在onStop()。


(老子可翻译完一篇了,翻译着还真难,好多句子都不通顺,再接再厉)