2.4 屏幕切换
在一般情况下,Android的每一个屏幕基本上是一个活动(Activity),屏幕之间的切换实际上就是在活动间互相调用的过程,在程序中通过使用Intent完成屏幕跳转的动作。
Android屏幕跳转的关系和方式如图2-8所示。
图2-8 屏幕跳转的关系和方式
从程序的角度,屏幕之间“切换”的过程实际上是一个屏幕启动了另外一个屏幕。从一个Activity启动另外一个Activity的结果是“跳转”,也就是“屏幕的切换”。在Android中有如下两种类型的跳转。
startActivity():简单启动一个屏幕;
startActivityForResult():以带有返回结果的方式启动一个屏幕。
另外一个方面,如果A屏幕(活动)启动B屏幕之后,自己退出,那么这将是一个没有返回的跳转;如果A屏幕启动B之后,自己没有退出,那么B退出的时候可能又返回到A,这就是一个可返回的跳转。显然,只有在启动者没有退出的情况下,才有返回结果接收的问题。
2.4.1 启动活动的方法
Activity等类继承自Context,Context中的startActivity()方法用于启动一个简单的活动,如下所示:
public void startActivity (Intent intent)
Intent用于传递两个屏幕之间的信息,实现屏幕的跳转功能。调用者可以通过Intent传递参数,也可以获得跳转对象的返回信息。Android中的各个屏幕一般是对等的,具有启动关系的两个屏幕没有运行时的依赖关系。
本示例是一个简单的屏幕之间的跳转,从一个屏幕跳转到另一个屏幕,在启动第二个屏幕后,前一个屏幕消失。
示例程序:Forward(ApiDemo=>App=>Activity=>Forward)
源代码:
com/example/android/apis/app/Forward.java com/example/android/apis/app/ForwardTarget.java
本示例包含了两个活动,在UI上它们就是两个屏幕,分别为跳转的源和目的,它们在AndroidManifest.xml中的定义如下所示。
<activity android:name=".app.Forwarding" android:label="@string/activity_forward ding"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> <activity android:name=".app.ForwardTarget"> </activity>
两个活动的名称分别为Forwarding和ForwardTarget,由于第二个活动没有intent-filter,因此在程序中只能由第一个活动来启动。
Forwarding程序的运行结果如图2-9所示。
图2-9 活动的跳转程序运行结果(左Forward;右ForwardTarget)
在第一个活动(Forwarding)启动后,单击“Go”按钮跳转到第二个活动(ForwardTarget)。第二个活动退出后,不会返回到第一个活动。
跳转的核心内容在Java源文件Forward.java的以下片段中处理:
public void onClick(View v) { Intent intent = new Intent(); // 建立Intent intent.setClass(Forwarding.this, ForwardTarget.class);//在Intent中设置活动目标 startActivity(intent); finish(); // 结束当前活动 }
启动第二个活动需要使用Intent,在其setClass()方法中设置源和返回的内容,Intent是android.content包中的类,用于启动活动、服务或者消息接收器。
这里使用的Intent的setClass()方法的原型如下所示:
Intent setClass(Context packageContext, Class<?> cls)
第一个参数是当前的上下文类型Context,因此把当前的活动设置过去即可(Activity本身继承了Context),第二个参数是Intent所包含的Java类,直接设置ForwardTarget.class类即可。
本例中使用了finish()方法表示当前的活动结束,这样在第二个活动(ForwardTarget)启动时,第一个活动(Forward)已经不存在了。如果没有调用finish()方法,第二个活动启动时,第一个活动就会进入停止状态,onPause()和onStop()方法将被接连调用。当第二个活动退出后,第一个活动重新出现,也就是会调用其中的onStart()和onResume()方法。
2.4.2 带有返回结果的启动活动
在某些时候,从跳转的对象返回时,跳转源屏幕需要得到其返回的结果,这样两个屏幕可实现一些交互的效果。
Activity中的以下几个方法运动启动带有返回结果的跳转,如下所示:
public void startActivityForResult (Intent intent, int requestCode) public void finishActivity(int requestCode) protected void onActivityResult (int requestCode, int resultCode, Intent data)
startActivityForResult()可以取得返回结果的活动启动方法;finishActivity()用于结束一个使用startActivityForResult()启动的活动;onActivityResult()用于接收被启动的Activity返回的结果。
提示:上述几个方法只能在Activity中使用,启动者和被启动者之间有所关联。
一个被以startActivityForResult()方式启动的活动,可以使用setResut()方法设置内容给其启动者:
public void setResut(int resultCode, Intent intent)
按照这种模式,在Activity的启动者和被启动者之间,进行传递的数据有如下4个。
启动Intent:由启动者传递给被启动者,含义和没有返回结果的启动相同;
请求码(int类型):由启动者传递给自己;
返回码(int类型):由被启动者传递给启动者;
返回数据(Intent类型):由被启动者传递给启动者。
后三个也就是启动者的onActivityResult()中所接收的三个参数,其中返回码有以下的Activity类的几个默认数值:
public static final int RESULT_OK // -1 public static final int RESULT_FIRST_USER // 0 public static final int RESULT_CANCELED // 1
以下程序用于一个带有返回结果的活动。
参考示例程序:ReceiveResult(ApiDemo => App=>Activity=>ReceiveResult)
源代码:
com/example/android/apis/app/ReceiveResult.java com/example/android/apis/app/SendResult.java
ReceiveResult程序的运行结果如图2-10所示。
图2-10 带有返回结果的跳转运行结果(左:ReceiveResult;中:SendResult;右:ReceiveResult)
初始化界面如图2-10中左图所示,单击“Get Result”按钮将跳转到第二个屏幕,如图2-10中的中图所示;在第二个屏幕中单击“Corky”和“Violet”按钮将返回第一个屏幕,如图2-10中的右图所示。右图中显示的也就是返回结果的内容。
Java源文件ReceiveResult.java的代码片段如下所示:
static final private int GET_CODE = 0; private OnClickListener mGetListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(ReceiveResult.this, SendResult.class); startActivityForResult (intent, GET_CODE); // 带有返回结果的跳转 } };
这里调用的是startActivityForResult()方法,设置一个GET_CODE为请求代码,这样可以获得目标活动的返回信息。这个方法的原型为:
public void startActivityForResult (Intent intent, int requestCode)
被跳转的目标Java源文件SendResult.java的代码片段如下所示:
private OnClickListener mCorkyListener = new OnClickListener() { public void onClick(View v) { setResult(RESULT_OK,(new Intent()).setAction("Corky!"));// 设置返回结果 finish(); // 结束SendResult } }; private OnClickListener mVioletListener = new OnClickListener() { public void onClick(View v) { setResult(RESULT_OK,(new Intent()).setAction("Violet!"));// 设置返回结果 finish(); // 结束SendResult } };
被跳转的目标程序将返回值返回,这里使用的依然是Intent作为交互的信息,通过setAction()设置不同的活动。
由于被跳转的目标程序是被显示Intent调用起来的,因此,返回后继续由ReceiveResult.java对返回值进行处理。返回的信息通过重新实现Activity的onActivityResult()方法来实现,两个整数类型的参数requestCode和resultCode分别代表请求代码和结果码,第三个参数Intent(类型data)表示活动间交互附加的数据信息。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == GET_CODE) { Editable text = (Editable)mResults.getText(); if (resultCode == RESULT_CANCELED) { // 处理程序使用回退按键返回的情况 text.append("(cancelled)"); } else { // 处理程序使用setResut()返回的情况 text.append("(okay "); text.append(Integer.toString(resultCode)); text.append(") "); if (data != null) { text.append(data.getAction()); // 将设置返回数据的动作 } } text.append("\n"); } }
这里onActivityResult()是一个被继承的方法,其参数data就是这个活动接收到的返回结果,data.getAction()可以从返回的Intent中取回内容。
参数requestCode对应于调用startActivityForResult()的时候启动活动时指定的申请码。其作用在于,一个活动启动了多个活动的时候,根据这个requestCode可以区分是哪一个活动返回了。参数resultCode比较特殊,当把启动的程序自己返回的时候,这个数值可以由被启动的程序设置。如果被启动的程序被使用回退按键返回,那么这个数值将为RESULT_CANCELED(0)。
对于resultCode,虽然其类型是整型,但是由于它有几个默认值(Activity类中定义的-1,0,1)用于处理特殊情况,因此,如果用其表示自定义的结果,它只能表示枚举类型,不足以表示整数类型的数据(会和特殊情况有冲突)。更多的返回结果,应该通过Intent来表示。