本节书摘来自异步社区《Android 开发入门与实战(第二版)》一书中的第6章,第6.9节Activity小实例,作者eoe移动开发者社区 组编 , 姚尚朗 , 靳岩,更多章节内容可以访问云栖社区“异步社区”公众号查看
6.9 Activity小实例
Android 开发入门与实战(第二版)
在介绍完Activity相关基础内容后,现在我们来针对Activity开发一个简单的小实例。
这个实例指定了3个界面(Activity)。HelloWorldActivity界面有两个按钮,Button 1和Button 2(见图6-3),Button 1单击后会跳转到Activity B,而Activity B简单地显示“This is Activity B,Welcome!”(见图6-4)。单击Button 2后则跳转到Activity C,Activity C界面有一个输入框以及一个“确定”按钮(见图6-5),当单击“确定”按钮之后,将关闭Activity C,并获取输入框中的内容,回传到HelloWorldActivity,并将回传的内容显示在Button2的下方,如图6-6所示。
第X问1 实例编程实现
第1步:新建一个Android项目(相信大家看完前面的章节已经知道如何去创建一个Android项目了,这里就不再赘述),并创建包名,3个Activity(全部继承自Activity类,并重写onCreate方法)以及3个布局文件。如图6-7所示。
第2步:打开main.xml布局文件,编写如下代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"/>
<Button android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"/>
<TextView android:id="@+id/tvDisplay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
第X问1 代码解释
定义一个LinearLayout(线性布局),并在这个布局中定义两个Button和一个TextView控件。两个Button的长和宽都是wrap_content(包裹住内容)就可以了。TextView的宽度则是fill_parent(填满父控件)。
注意
上述代码中的Button控件的android:text属性的值理应放置在项目结构中values文件夹下strings.xml文件中定义,并采用@string/xxx来引用对应的值。由于这里主要是介绍Activity,所以就直接将值写在了属性后面。
第3步:打开activityb.xml布局文件,编写如下代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tvActivityb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is ActivityB,Welcome!"/>
</LinearLayout>
第X问1 代码解释
这里只是定义了一个线性布局,并在布局中定义了一个Textview控件,并显示“This is ActivityB,Welcome”字样。
第4步:打开activityc.xml布局文件,编写如下代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/etActivityc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button android:id="@+id/buttonc1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定"/>
</LinearLayout>
第X问1 代码解释
定义一个线性布局,并在布局中定义一个EditText和Button控件。
第5步:打开HelloWorldActivity.java文件,找到onCreate方法,编写如下代码。
//将布局文件设置为main.xml
setContentView(R.layout.main);
//得到两个Button控件
Button mButton1 = (Button)findViewById(R.id.button1);
Button mButton2 = (Button)findViewById(R.id.button2);
//为Button1绑定单击事件
mButton1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//使用intent启动ActivityB
Intent _intent =
new Intent(HelloWorldActivity.this, ActivityB.class);
startActivity(_intent);
}
});
第X问1 代码解释
HelloWorldActivity首先将main.xml文件设置为布局文件,之后通过findViewById方法得到两个Button控件,由于先打算实现单击Button1跳转到ActivityB这个功能,我们暂时只为Button1绑定单击事件。
Intent _intent =
new Intent(HelloWorldActivity.this, ActivityC.class)
语句新建了一个Intent,这个Intent描述了从HelloWorldActivity跳转到ActivityB的一次操作。
startActivity(_intent)语句用来启动_intent,由_intent描述的这次操作才正式执行。
小知识
什么是Intent?在Android官方文档中是这么定义的,Intent是一次即将操作的抽象描述,现在理解这个定义还有些抽象,但是看完本书就会对这个定义理解了。在Android当中,一共用到了3种Intent,现在使用的是第一种,它的作用就是启动一个新的Activity并且可以携带数据。还有两种分别如下:
(1)通过Intent启动一个服务(Service)。
(2)通过Intent广播事件。
以上两种我们会在后续的章节讲到,这里不再细述。
第6步:打开ActivityB.java文件,这个文件中没有复杂的代码,只是将activityb.xml文件设置为ActivityB的布局文件。具体代码如下。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityb);
}
通过这一步之后,从HelloWorldActivity跳转到ActivityB就已经完全实现了。接下来就要实现稍微复杂一点的从HelloWorldActivity跳转到ActivityC,并得到返回值显示在HelloWorldActivity的逻辑了。
第7步:重新打开HelloWorldActivity.java并为Button2添加监听事件,具体代码如下。
mButton2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent _intent =
new Intent(HelloWorldActivity.this, ActivityC.class);
startActivityForResult(_intent, 100);
}
});
第X问1 代码解释
Intent _intent =new Intent(HelloWorldActivity.this,ActivityC.class)跟Button1一致,也是描述一次从HelloWorldActivity到ActivityC的跳转操作。不同的是,这次启动时,使用的方法是startActivityForResult()方法。
上述代码中的startActivityForResult方法有两个参数,第一个是intent对象,还有一个则是“请求码”(requestCode),这个请求码是用来区分不同的请求。
例如,A Activity使用了startActivityForResult方法启动了B Activity以及C Activity,在回调的时候,A Activity中的回调方法只有一个,这样,我们就能够根据不同的requestCode在不同的时机只取B Activity或C Activity返回的值。
小知识
startActivity与startActivityForResult的区别。
startActivity在启动了其他Activity之后是不会再回调回来的,相当于启动者与被启动者在启动完毕之后是没有关系的。
startActivityForResult在启动了其他Activity之后是有回调的,也就是说启动者与被启动者在启动完毕之后依然是有关系的。
第8步:前面我们已经在HelloWorldActivity中为Button2添加了事件并使用startActivityForResult来启动ActivityC,现在我们看看ActivityC又需要做些什么呢?关键代码如下所示:
//设置activityc.xml为布局文件
setContentView(R.layout._activityc_);
//得到Button实例
Button button1 = (Button)findViewById(R.id._buttonc1_);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//实例化一个intent对象
Intent data = new Intent();
//获取EditText实例
EditText editText = (EditText)findViewById(R.id._etActivityc_);
//得到EditText的值
String val = editText.getText().toString();
//将EditText的值存到intent对象中(以键值对的形式)
data.putExtra("helloworld", val);
//调用setResult方法,将intent对象(data)传回父Activity
setResult(Activity._RESULT_OK_, data);
//关闭当前Activity
finish();
}
});
第X问1 代码解释
从上面的代码注释中也能了解到,先是获取了EditText这个控件对象,并使用editText.getText().toString()得到EditText中输入的值,再通过intent的putExtra方法将获取的值以键值对的形式存入Intent中,之后调用setResult方法将成功的状态码以及intent对象传到父Activity(HelloWorldActivity)中。
小知识1
Intent在传递数据时提供了putExtra和对应的getExtra方法来实现存值与取值。而这里的put和get方法其实和Bundle的put,get方法是一一对应的。在Intent类中有一个Bundle的mExtras成员变量,所有的putExtra和getExtra方法实际上都是调用mExtras对象的put和get方法进行存取。所以,在正常情况下,传递数据可以直接使用intent的putExtra和getExtra方法即可,无需再创建一个Bundle对象。
小知识2
Bundle类型。这里简单介绍一下,Bundle是一个类型安全的容器,它的实现就是对HashMap做了一层封装。对于HashMap来说,任何键值对都可以存进去,值可以是任何的Java对象。但是对于Bundle来说,同样是存键值对,但是这个值只能是基本类型,或者基本类型数组,比如int,byte,boolean,char等。
如果大家对Bundle的概念还是有点模糊,没关系,在以后的学习过程中会慢慢了解,这里只需要知道,我们可以使用Intent对象的putExtra和getExtra方法来存取数据就行了。
第 9 步:在完成了Activity C.java文件的代码编写后,我们接着再继续打开HelloWorldActivity文件,最开始,我们在HelloWorldActivity中实现了Button 2的事件,这个事件启动了对Activity C的调用,而在Activity C中我们刚刚也得到了一个EditText对象的值并通过setResult方法回传到了父Activity(HelloworldActivity),那么现在我们就需要在HelloworldActivity中来实现我们的回调函数了。具体代码如下。
@Override
protected void onActivityResult(int requestCode,int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 100 && resultCode == Activity._RESULT_OK_){
String val = data.getExtras().getString("helloworld");
TextView textView = (TextView)findViewById(R.id._tvDisplay_);
textView.setText("来自ActivityC的值 :"+ val);
}
}
第X问1 代码解释
if(requestCode == 100 && resultCode == Activity.RESULT_OK)这句代码是判断requestCode是不是等于当初你在startActivityForResult方法中设置的requestCode,并且ActivityC返回的resultCode是不是等于RESULTOK_,如果是,则通过data.getExtras().getString("helloworld")获取ActivityC中通过putExtra方法存的值。得到值之后,再获取main.xml布局文件中的TextView控件,并将值赋给它显示出来。
第 10 步:这也是最容易被忽视的一步,我们所有的Activity都必须在Androidmanifest.xml文件中进行注册,如果不注册,程序将会出错。具体注册代码如下。
<activity android:name=_".ActivityB"_/>
<activity android:name=_".ActivityC"_/>
注册完毕之后,整个实例就完成了,赶紧运行试试看吧!