《Android 开发入门与实战(第二版)》——6.9节Activity小实例

本节书摘来自异步社区《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所示。


《Android 开发入门与实战(第二版)》——6.9节Activity小实例

第X问1 实例编程实现

第1步:新建一个Android项目(相信大家看完前面的章节已经知道如何去创建一个Android项目了,这里就不再赘述),并创建包名,3个Activity(全部继承自Activity类,并重写onCreate方法)以及3个布局文件。如图6-7所示。


《Android 开发入门与实战(第二版)》——6.9节Activity小实例

第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"_/>

注册完毕之后,整个实例就完成了,赶紧运行试试看吧!

上一篇:activiti自定义流程之Spring整合activiti-modeler5.16实例(九):历史任务查询


下一篇:EmEditor的一个好用的正则替换功能