一 Activities
这个东东相当于一个屏幕,你也可以理解成一个窗口,反正你就能在它上面操作,不管你是用它来发邮件还是打电话,这个东西会充满整个屏幕,就算窗口尺寸比屏幕小,它也会满屏的漂浮在窗口的最顶层。
一个程序可能有多个activities,但是一定要有一个是“main”activities,程序一旦运行起来,就首先加载这个main。每个activities又可以加载其他activities,每次启动新的activities,前面一个将被放到所谓的“后台堆栈”,这些后台堆栈遵循“后进先出”的原则,所以当你按back键的时候,你看到的是上一屏,也就是上一个activities。
当一个新的activities启动而旧的activities被停止的时候,有个叫callback的方法会放到这个activities的状态里面。有好几种callback的方法,在于你赋予什么属性给它,当你使用stop的时候,很多对象将会释放,例如网络或者数据库连接等等,如果仅仅是resume,你还可以继续在这个activities里面查询你需要的东西。看得不太明白,以后再说。
1.1创建一个activities
要创建一个activities,你必须是创建一个Activities子类,或者其他Activities子类的子类,也就是孙子类?你的activities必须实现callback方法,系统才能在它的生命周期中调用它的时候才知道到底要干吗,例如停止它,创建它,摧毁它还是怎么着。其中有两个最重要的方法:
onCreate()
你必须实现这个方法,系统靠它来启动创建activity。在实现这个方法的过程中,你必须初始化一些基本的组件。特别重要的是,你必须调用setContentView()来定义你的UI布局。
onPause()
系统在用户离开这个activity的时候调用这个方法,这个一般是在你还需要上一个用户session的时候使用的。
还有很多种callback的方法来实现你不同的需要,这些我们晚点再讨论。
1.1.1实现一个用户界面
一个activity的用户界面由Views的派生对象hierarchy提供。每个view控件控制一个特殊的长方形空间,并可以对用户动作作出反应。例如,某个view控件包含一个按钮,当用户触发这个按钮的时候就可以初始化某行为。
Android提供很多可视views控件供你设计的时候选择,这些玩意都放在了Widgets面板下,例如按钮,文本输入框,选择框等等。Layouts是另外一个views,它由ViewGroup派生出来,它提供特殊的架构模型,例如线性的布局,表格性的布局等。你也可以在View或者ViewGroup下构建属于你自己的子类,以方便你以后的使用。
最常用的办法就是使用你程序源代码下面的xml文件来定义你的布局。这样,你就可以自由的修改你的用户布局,而不影响activity的行为。也就是所谓的分层吧。你还可以通过setContentView的方法来使用你的布局作为用户界面。当然,你还可以在ViewGroup下插入新的Views代码,然后使用setContentView的办法来调用。更多的内容请查看User Interface那章。
1.1.2 在manifest下面声明activity
你必须在manifest下面声明你的activity。方法很简单,打开你的manifest然后在<application>元素下加入一个<activity>子元素。
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
在这里你还可以定义activity的很多属性,例如标签,icon,主题。更多的内容请参阅<activity>参考资料。
1.1.3 使用intent filters
一个<activity>元素可以通过定以<intent-filter>元素来指定多种intent filters,这样就声明了其他程序组件将通过什么方式激活这个activity。
当你使用android sdk工具来创建一个新的activity,它将自动生成一个intent filter,并声明通过main动作激活它,而这个filter必须在LAUCHER目录下。例如:
<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>
上述代码表明,这个activity是程序的main的启动点,同时,<category>元素指定这个activty应该在应用的launcher下,也就是允许用户调用的activity。
如果你希望你的activity仅仅是本程序可以访问,不允许其他程序访问,你不需要做任何的修改,如果你希望你的activity对其他应用作出反应,你就需要增加新的intent filters。
2011-3-14
1.2启动一个activity
你可以调用startActivity()来启动一个新的activity,通过Intent来定义你要启动的activity。Intent会指定准确的activity你希望启动或者描述。在启动的时候一个intent还可以传递少量的数据。
下面的代码简单的告诉你如何启动一个名叫SignInActivity
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
然而,你的应用可能需要实现一个动作,比如发送一封邮件,一条短信,或者调用一些activity的数据。在这情况下,你的activity不一定需要属于自己的行为来实现这些动作,你可以调用设备上的其他应用程序来实现这些动作。这就是intent的价值所在,你可以通过它调用任意一个外部应用程序的activity。如果有多个activity可以处理你的intent,用户可以自由选择。下面代码展示如果发送邮件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
上述代码说明,EXTRA_EMAIL是一串收件人的地址数组,当一个发送邮件程序回应这个intent的时候,自动读取到收件人数组并放到收件人栏,流程大概这样,发送邮件程序的activity启动并完成发送动作后,你的activity被重新调用放到前台来。
1.3 获取activity运算结果
如果你想得到一个activity的运算结果,你就是用startActivityForResult(),而不是使用startActivity()。使用onActivityReult()的callback方法去获取子activity的结果的时候,结果会保存在一个intent里面并传给你的onActivityResult()方法。
比如,你希望用户从他的电话簿里面选择一个联系人出来干点什么事情….
private void pickContact() {
// 创建一个新的intent,以便选择联系人,CONTENT_URI是android共享平台的数据方法
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) {
//逻辑判断:如果请求顺利并且请求是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()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// 给选中的联系人干点啥...
}
}
}
上述代码展示如何使用onActivityResult()来处理activity结果的最基本逻辑。首先是根据resultCode来判断request请求是否成功,然后再判断requstCodes是否符合startActivityForResult()的第二个参数,在这个例子里面,查询的结果返回intent里面来,也就是data的参数。后面就是指针去定位数据完全操作等,不赘述。
1.4 关闭一个activity
你可以调用finish()方法来关闭一个activity,也可以使用finshiActivity的方法关闭一个之前打开的activity。
注意:很多时候,你不需要用这个办法来关闭你的activity。正如前面所述,android平台会自动管理你的activity的生命周期。除非你肯定不需要你的用户使用这个activity,要不使用这个办法来关闭activity会大大的伤害用户的体验。
1.5 管理activity的生命周期
使用callback的办法来管理你的activty的生命周期可以构造出强大的、灵活的应用程序。一个activity的生命周期和其他调用它的activity息息相关。
一个activity可以表现成如下三种状态:
Resumed:可以理解成正在运行状态,处在屏幕的最前端并处在用户焦点内。
Paused:其他activity正处在运行的状态,但是这个activity还是可见的状态。也就是说其他activity在它之上,它变得部分透明或者不能覆盖整个屏幕,一个Paused的activity还处在内存中的活动状态,而且在window manager可见,但是如果系统内存严重不足的时候,会被干掉。
Stopped:这个activity已经彻底的不可见,转到后台运行。这个状态下它还会保留在内存中,但是在window manager中不可见了。当系统需要新的内存的时候它将会被干掉。
当一个activity处在Paused或者Stopped的状态,系统可以随时干掉它,也就是finish()方法所干的一样,如果你还需要它的时候,你就必须再次启动它。
1.5.1 实现生命周期的回调
当一个activity是上述状态的时候,你可以使用很多种办法回调它。下面的代码将展示如何实现回调的方法
public class ExampleActivity extends Activity {
@Override
public voidonCreate
(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// activity开始创建
}
@Override
protected voidonStart()
{
super.onStart();
//activity准备处在可见状态.
}
@Override
protected voidonResume()
{
super.onResume();
// activity已经可见 (处在resumed状态).
}
@Override
protected voidonPause()
{
super.onPause();
// 其他activity开始可见(这个activity变成了paused状态).
}
@Override
protected voidonStop()
{
super.onStop();
// activity不再可见(处在stopped状态)
}
@Override
protected voidonDestroy()
{
super.onDestroy();
//activity不再存在
}
}
请注意,你每次使用callback方法前,你都需要重新实现父类。
2011-3-15
如上,你可以观察到一个activity的生命周期的嵌套循环过程。
·整个生命周期:从onCreate()开始到onDestory()结束。前者是所有线程的开始,后者是所有线程的释放。
·可视化状态生命周期:从onStart()开始到onStop()结束。这个状态中,用户可以看到这个activty并且可以与之交户。
·foreground lifetime ,可以理解成在前景状态。从onResume开始到onPause结束,这个状态期间,activity在所有屏幕的前端,并且获得用户焦点。一个activity可以频繁的变换其foreground状态。由于需要频繁转换,调用这两个方法的代码必须是轻量级的。
下面的图片将会说明一个activity的不同状态和调用方法等关系,并说明不同状态的之间。
1.6 保存activity的状态
在前面的介绍中,我们说过activity的如果改到了paused或者stopped的状态的时候,它还是继续保留在内存中。当你使用resume方法调出的时候,用户曾经做过的修改等都还保存在内存里面。
然而,当系统需要更多的内存来运作其他东西的时候,系统会选择干掉你的activity,也就是所谓的destroyed,你就不能resume它了。如果这时候用户使用back按钮回调这个activity的时候,系统只能重新创建它了,但是用户不知道这样的机制,他们还以为之前操作过的东西都还在呢。所以,你必须保留在系统干掉你的activity之前就保存一些重要的信息,以便下次系统重新创建它的时候可以修复回去。
Callback方法里面,你可以使用onSaveInstanceState()的办法来保存你activity的信息。如果你使用了这个办法,系统在干掉你的activity之前会把它保存成一个Bundle对象。你就可以使用这个对象和putString方法来修复你的数据了。
注意:没有人担保系统在干掉activity之前一定会调用这个onSaveInstanceState()来保存你的数据。
1.7 处理配置的改变
在你的activity运行期间,一些设备上的配置可能会发生改变,这个时候,android系统自动的重新启动你的activity(先是onDestroy,然后再onCreate),这样你的程序就可以自动适应新的配置。
为了使你的程序可以自动适应新的配置,最好的办法就是用之前办法,先onSaveInstanceState然后再onCreate。
1.8 协调多个activity
当多个activity开始启动的时候,我们需要了解他们的运行机制。下面我们把这些顺利理一下:
A) activity A onPaused
B) activity B 马上开始执行onCreate或者onStart
C) 当这个activity不再需要的时候,开始执行onStop方法。
根据上述机制,你就可以轻松的掌握如何把数据从一个activity传递到下一个activity。比如,你想把数据写到数据库里面,让下一个activity可以使用它的时候,你就需要使用onPause方法而不是使用onStop方法。See?