android 应用基础(Activities)

一个Activity是一个应用程序组件,提供一个屏幕,用户可以为了做一些事情,比如拨打电话,拍照,发送电子邮件或查看地图等。每个活动都有一个窗口,在其中绘制它的用户界面。该窗口通常充满屏幕,但可能会比屏幕小并且浮在其它窗口之上。


一个应用程序通常包括被松散地结合到彼此的多个活动。典型地,在一个应用程序主(main)Activity,这是在启动应用程序时呈现给用户。然后,每个Activity开始运行,以执行不同的动作到另一个活动。每当一个新的活动开始时,先前的活动停止了,但系统保留了Activity的栈( “back stack”) 。当一个新的Activity开始,它被压入堆栈回来,并取得用户关注的焦点。后退堆栈遵守基本的“后进先出”的堆栈机制,所以,当用户完成与当前活动,并按下返回按钮,将其从堆栈中弹出(和销毁)和以前的Activity恢复。


一个新的Activity开始后,通过活动的生命周期回调方法通知原来的Activity状态改变。一个可能会收到好几种回调方法,无论系统创建它,阻止它,恢复它,或者摧毁它,并且每次回调为你提供的不同的方法以执行特定的工作。例如,停止时,你的活动应该释放任何大的物体,如网络或数据库连接。当活动恢复,您可以重新获取必要的资源,并恢复了被打断的行动。这些状态转换都是活动的生命周期的一部分。

创建一个Activity

要创建一个活动,你必须创建活动的子类(或它的一个子类存在),也就是继承Activity类。在你的子类,你需要实现系统调用时,它的生命周期的各种状态,在创建活动时,如之间的活动过渡,停止,恢复或销毁回调方法。最重要的两个回调方法是: 


onCreate() 
必须实现。创建活动时,系统调用这个。在你执行,你应该初始化你的活动的重要组成部分。最重要的是在这个方法里面你必须调用的setContentView()来定义的布局为活动的用户界面。 
onPause() 
用户离开你的活动(尽管它并不总是意味着该活动被破坏)系统会调用这个方法。这通常是你应该承担的是持久的超出当前用户会话的任何变化(因为用户可能不回来)。 

还有,你应该以提供活动之间的流畅的用户体验和处理判退意外,导致你的活动必须停止,甚至摧毁了使用其他一些生命周期回调方法。所有的生命周期回调方法将在后面讨论,在有关管理活动生命周期的部分。

实现用户界面

为活动的用户界面是由View类派生的层次结构的视图。每个视图控制特定的矩形空间中的活动窗口内,并可以对用户交互作出响应。例如,一个视图可能是一个按钮,当用户触摸它启动一个动作。 


Android提供了一些现成的视图,你可以用它来设计和组织你的布局。 “Widgets”是一个提供对屏幕的可视(和交互)元素,诸如按钮、文本字段、复选框、或图像的视图。 “Layouts”是从ViewGroup引出的,可以认为是它的子视图,如线性布局,网格布局,或相对布局独特的布局模式。您也可以继承的View(视图)和ViewGroup(视图组类)(或现有的子类)来创建自己的控件和布局,并把它们应用到你的活动布局。 


使用视图定义布局最常见的方法是使用保存在您的应用程序资源的XML布局文件。通过这种方式,可以单独从源代码中定义的活动的行为保持用户界面的设计。您可以设置布局作为UI与的setContentView()你的活动,通过资源ID为布局。但是,您也可以在您的活动代码中创建新视图并加入新的浏览到一个视图组构建一个视图层次结构,然后使用该布局通过传递根视图组来的​​setContentView()。 

在Manifast中发布你的Activity

你必须在manifest文件中声明活动,以便它可以被访问到系统中。要声明你的活动,打开你的manifest文件,并添加一个<activity>元素作为<application>元素的子元素。例如:

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

还有其他一些属性,这些属性可以包含在这个元素来定义,如标签的活动,该活动的图标,或者一个主题样式化活动的UI属性。在android:name属性是唯一必需的属性,它指定了活动的类名。一旦你发布你的应用程序时,你不应该更改此名称,因为如果你这样做,你可能会破坏一些功能,如应用程序的快捷方式(阅读博客文章,事情,不能更改)。


使用Intent过滤器

一个<activity>元素也可以指定不同的Intent过滤器,使用<intent-filter>元素,以如何申报其他应用程序组件可以激活它。

当您创建使用Android SDK工具的新应用程序,这是为你自动创建存根活动包括一个Intent过滤器,声明该活动响应“main”操作,并应放置在“launcher”的范畴。这个过滤器就像这样:

<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>元素指定这是“main”到应用程序的入口。该<category>中元素指定这个Activity应该在系统应用启动时被监听(允许用户启动此活动)。 

如果你打算为你的应用程序是自包含的,而不是让其他应用程序来激活它的活动,那么你不需要任何其他Intent过滤器。仅仅一个活动应该有“main”行动和“launcher”的范畴,就像前面的例子。对于你不让它进入其他Activity的Activity,你不需要设置Intent过滤器,你只要使用明确地Intent。

但是,如果你希望你的Activity到从其他应用程序(和你自己)交付隐含意图做出回应,那么你必须为你的活动定义附加的意图过滤器。对于每种类型的您要回应的Intent,则必须包括<intent-filter>,其中包括一个<action>元素和一个可选的<category>中的元素和/或<data>元素。这些元素指定Intent,你的Activity可以响应的类型。 

创建一个Activity

你可以通过调用的startActivity(),传递给它的描述要启动该Activity的intent开始另一个活动。这样做的目的不是指定你想要启动的确切活动或描述要执行(系统会自动选择适当的活动对你来说,这甚至可以从不同的应用程序)的操作的类型。意图也可以进行要使用的启动,该活动少量数据。 

当在自己的应用程序时,你会经常需要简单地推出一个已知的活性。你可以通过创建明确定义你想要启动的活动,使用类名的意图这样做。例如,下面是一个Activity开始还有一个叫SignInActivity:

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

但是,您的应用程序可能还需要执行一些操作,如发送电子邮件,短信或状态更新,使用从您的活动数据。在这种情况下,您的应用程序可能没有自己的活动来执行这样的行动,这样你就可以充分利用,而不是通过设备上的其他应用程序,它可以执行的操作为您提供的活动。这就是Intent是真正有价值的,你可以创建一个描述要执行,系统从另一个应用程序启动相应的活动的诉讼意图。如果有多个活动,可以处理的意图,那么用户可以选择使用哪一个。例如,如果你想允许用户发送电子邮件时,您可以创建以下目的:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
额外添加的Intent EXTRA_EMAIL是该邮件要发送的电子邮件地址的字符串数组。当电子邮件应用程序响应这个Intent,它读取额外提供的字符串数组,并将它们放在电子邮件的形式组成的“to”字段中。在这种情况下,电子邮件应用程序中的活动开始,当用户完成后,您的活动恢复。

启用一个带返回的Activity

有时候,你可能会想从你开始的活动获得的结果。在这种情况下,启动通过调用startActivityForResult()(代替的startActivity())。为了再从后续活动获得的结果,实现onActivityResult()回调方法。在随后的活动完成后,它将返回一个结果的意图在你的onActivityResult()方法里。

例如,也许你想挑选自己的联系人之一的用户,所以你的活动可以做一些与信息的接触。这里是你如何能创造这样的意图和处理的结果:

private void pickContact() {
    // 创建一个Intent来获得关联, 通过被定义在contentprovider上的 URI
    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) {
    // 如果请求很顺利 (OK) 同时请求码为PICK_CONTACT_REQUEST
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
        // 表明执行查询到联系人的内容提供商的联系人的姓名
        Cursor cursor = getContentResolver().query(data.getData(),
        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor.moveToFirst()) { // 如果cursor不为空,true
            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
            String name = cursor.getString(columnIndex);
            // 在这里可以对name做一些处理...
        }
    }
}
这个例子显示,你应该在你的onActivityResult()为了处理一个活动的的基本逻辑。第一个条件检查该请求是否成功,如果是,则发送resultCode为RESULT_OK和是否这此结果是响应该请求是已知的,在这种情况下,requestCode()与startActivityForResult()发送的所述第二参数相匹配。从那里,代码处理通过查询在一个Intent(数据参数)返回的数据的活动成果。 

关闭一个Activity

调用finish()方法来关闭Activity.你也可以用finishAcivity()来结束之前的Activity。


管理Activity的生命周期

管理您的活动通过实现回调方法的生命周期是非常重要的发展强大和灵活的应用。一个活动的生命周期直接影响其协会与其他活动,它的任务并返回堆栈。

一个Activity基本有这三种状态:

1.Resumed(恢复 )

该活动是在屏幕的前景中,并具有用户的焦点。 (这种状态也有时简称为“运行”。) 

2.Paused(已暂停 )

另一项活动是在前台,拥有焦点,但是这一次仍然是可见的。也就是说,另一个活动是可见的,这其中的顶部和该活动是部分透明或不覆盖整个屏幕。一个暂停的activity是完全活着(Activity对象保留在内存中,它保持所有状态和成员信息,并保持附着在窗口管理器),但可以通过该系统在内存严重不足的情况​​下被杀死。 

3.Stopped (停止 )

该活动是由另一个活动完全遮蔽(该活动是目前在“背景”)。停止的活动也仍然活着(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.
    }
}

总而言之,这些方法定义了一个活动的整个生命周期。通过实施这些方法,您可以在活动周期监视三个嵌套的循环:

调用的onCreate ()和调用的onDestroy ( )之间的活动的整个生命周期发生。您的活动应该执行设置的“global”的状态(如定义布局)中的onCreate ( ) ,并释放所有剩余资源的onDestroy ( ) 。例如,如果你的活动有在后台运行从网络下载数据的线程,它可以创建一个线程中的onCreate (),然后停止线程中的onDestroy ( ) 。
调用缓动()和调用的onStop ( )之间的活动的可视生命周期。在此期间,用户可在屏幕上看到的活性,并与它进行交互。例如,在onStop ( )当一个新的活动开始,这一次不再是可见的调用。这两种方法之间,可以保持所需要的,以显示活动给用户的资源。例如,您可以注册在OnStart中一个BroadcastReceiver ( ) ,以监测变化,影响你的UI ,并注销它的onStop ( )当用户不再能够看到你显示什么。该系统可能会在活动的整个生命周期内调用缓动( )和OnStop ()多次,作为可见和隐藏到用户之间的活动交替。
调用onResume ()和调用的onPause ( )之间的活动的前景一生发生。在这段时间内,该活动是在屏幕上的所有其他活动前面,并具有用户输入焦点。活动可以经常进入及退出前景,例如,在onPause ( )是当设备进入睡眠状态或将出现一个对话框时调用。因为这种状态通常可以转换,在这两种方法的代码应该是相当轻便的,以避免缓慢过渡,使用户的等待。

图1说明了这些循环和路径的活动可能状态之间关系。矩形表示你可以实现当活动状态之间的转换来执行操作的回调方法。



保存Activity的状态

引入到管理活动的生命周期简略的提到,当一个活动被暂停或停止,保持活动的状态。这是因为活动对象在内存中仍持有当它被暂停或停止,所有关于它的成员和目前的状态是还活着的信息。因此,任何的变化在活动范围内作出的用户将被保留,这样,当活动返回到前景(其“继续”时) ,这些变化仍然存在。

然而,当系统破坏的活性,以便恢复存储器,活动对象被破坏,所以其状态不变,系统不能简单地恢复它。相反,系统必须重新创建活动对象,如果用户返回到它。然而,在用户不知道的系统破坏了活动并重新创建它,因此,可能预期的活动是完全因为它是。在这种情况下,可以确保对活动状态的重要信息是通过实现一个额外的回调方法,可以让您保存有关活动的状态信息保存:的onSaveInstanceState ( ) 。

该系统调用的onSaveInstanceState ( )使得活动容易受到破坏之前。该系统通过该方法一个Bundle中,你可以了解该活动的状态信息保存为名称 - 值对,使用方法,如putString ( )和putInt ( ) 。那么,如果系统杀死你的应用程序和用户导航回你的活动时,系统将重新创建活动,并通过了捆绑到两个的onCreate ()和onRestoreInstanceState ( ) 。使用这两种方法,你可以从包中提取的保存状态和恢复活动状态。如果没有状态信息来恢复,然后捆绑传递给你的是空(也就是当活动第一次创建的情况下) 。


但是,即使你什么也不做,没有实现的onSaveInstanceState(),一些活动状态是由的onSaveInstanceState的Activity类的默认实现()恢复。具体来说,默认实现调用相应的onSaveInstanceState()方法用于在布局中,它允许每个视图提供应保存的关于自身的信息每个视图。在Android框架几乎每一个部件实现此方法适当,这样任何可见的变化对UI会自动保存,当你的活动被重新恢复。例如,EditText上小部件保存用户输入的任何文字,将CheckBox控件节约无论是检查还是没有。你所需要的唯一的工作是提供一个唯一的ID(用android:id属性)为您要保存其状态每个插件。如果一个widget没有一个ID,然后系统无法保存其状态。

虽然的onSaveInstanceState的默认实现()保存有关你的活动的UI有用的信息,你仍然可能需要重写它,以节省额外的信息。例如,您可能需要保存活动的生命(这可能关联到UI中的恢复值,但持有这些UI值的成员没有恢复,默认情况下)时,改变成员值。


因为的onSaveInstanceState的默认实现()有助于节省用户界面的状态,如果你为了节省额外的状态信息覆盖的方法,你应该总是在做任何工作之前调用超类实现的onSaveInstanceState()的。同样地,你也应该调用超类的实现onRestoreInstanceState的(),如果你重写它,所以默认实现可以恢复视图状态。

测试你的应用程序的恢复其状态的能力的一个好方法是简单地旋转装置,使屏幕的方向变化。当屏幕方向改变时,系统破坏并重新创建活动,以适用,可能是可用于新屏幕配置替代资源。仅仅出于这个原因,它是非常重要的,你的活动完全恢复其状态,当它被重新创建,因为用户在使用应用程序定期旋转屏幕。

处理配置更改 



有些设备配置可以在运行(如屏幕方向,键盘可用性和语言)期间改变。当这种变化发生时,机器人会重新运行活动(系统调用的onDestroy(),然后立即调用的onCreate())。这种行为的目的是帮助您的应用程序会自动重新加载应用程序与您所提供(如不同的布局不同的屏幕方向和大小)的替代资源,适应新的配置。 


如果你正确地设计自己的活动来处理重新启动由于屏幕方向的变化,恢复为上述活动状态,你的应用将更有弹性,以在活动生命周期的其他突发事件。 


处理这样一个重启的最好方法是保存和恢复您的活动的状态使用的onSaveInstanceState()和onRestoreInstanceState()(或的onCreate()),如前一节中讨论。 


如需在运行时发生以及如何处理它们的配置更改的详细信息,请阅读本指南处理运行时更改。 


协调活动 



当一个活动启动另一个,他们都经历生命周期的转换。第一项活动暂停和停止(虽然,它不会,如果它仍然可见在后台停止),而其他的活动被创建。若保存到光盘或其他地方的这些活动共享数据,重要的是要明白,在创建第二个之前的第一个活动是没有完全停止。相反,开始第二个的过程与停止的第一个过程中重叠。 


生命周期回调顺序是明确定义的,特别是当这两种活动都在同一个过程,一个是启动其他。下面是当活动A开始Acivity B中发生的操作顺序: 

活动A的在onPause()方法执行。 
活动B的OnCreate(),onStart()和onResume()方法的顺序执行。 (活动B现在有用户关注的焦点。) 
然后,如果活动A的onStop()方法执行在屏幕上不可见,。 
这个预测的生命周期回调的序列,可以管理从一个活动信息过渡到另一种。例如,如果你必须写一个数据库时的第一个活动停止,这样下活动可以读取它,那么你应该在onStop()中的onPause(),而不是写入数据库。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值