Android基础知识-Intent在活动间的传输

Intent在活动中最基本的两个使用方式:一个用于活动间的数据传输,一个用与活动间的跳转

一.使用Intent在活动中进行跳转
1.使用显式 Intent
你应该已经对创建活动的流程比较熟悉了,那我们现在快速地在 ActivityTest 项目中再
创建一个活动。新建一个 second_layout.xml 布局文件,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical" >
	<Button
	android:id="@+id/button_2"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:text="Button 2"
	/>
</LinearLayout>

我们还是定义了一个按钮,按钮上显示 Button 2。然后新建活动 SecondActivity 继承自
Activity,代码如下:

public class SecondActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	
	requestWindowFeature(Window.FEATURE_NO_TITLE);
	setContentView(R.layout.second_layout);
	}
}

最后在 AndroidManifest.xml 中为 SecondActivity 进行注册。

<application
	android:allowBackup="true"
	android:icon="@drawable/ic_launcher"
	android:label="@string/app_name"
	android:theme="@style/AppTheme" >
	<activity
	android:name=".FirstActivity"
	android:label="This is FirstActivity" >
	<intent-filter>
	<action android:name="android.intent.action.MAIN" />
	<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
	</activity>
	<activity android:name=".SecondActivity" >
	</activity>
</application>

由于 SecondActivity 不是主活动,因此不需要配置标签里的内容,注册活
动的代码也是简单了许多。现在第二个活动已经创建完成,剩下的问题就是如何去启动这第
二个活动了,这里我们需要引入一个新的概念,Intent。
Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组
件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动
服务、以及发送广播等场景,由于服务、广播等概念你暂时还未涉及,那么本章我们的目光
无疑就锁定在了启动活动上面。
Intent 的用法大致可以分为两种,显式 Intent 和隐式 Intent,我们先来看一下显式 Intent
如何使用。
Intent 有多个构造函数的重载,其中一个是 Intent(Context packageContext, Class<?> cls)。
这个构造函数接收两个参数,第一个参数 Context 要求提供一个启动活动的上下文,第二个
参数 Class 则是指定想要启动的目标活动,通过这个构造函数就可以构建出 Intent 的“意图”。
然后我们应该怎么使用这个 Intent 呢?Activity 类中提供了一个 startActivity()方法,这个方法
是专门用于启动活动的,它接收一个Intent参数,这里我们将构建好的Intent传入startActivity()
方法就可以启动目标活动了。
修改 FirstActivity 中按钮的点击事件,代码如下所示:

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
	Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
	startActivity(intent);
	}
});

我们首先构建出了一个 Intent,传入 FirstActivity.this作为上下文,传入 SecondActivity.class
作为目标活动,这样我们的“意图”就非常明显了,即在 FirstActivity 这个活动的基础上打
开 SecondActivity 这个活动。然后通过 startActivity()方法来执行这个 Intent。
重新运行程序,在 FirstActivity 的界面点击一下按钮可以看到,我们已经成功启动 SecondActivity 这个活动了。如想要回到上一个活动,按下 Back 键就可以销毁当前活动,从而回到上一个活动了。
这种方式来启动活动,Intent 的“意图”非常明显,因此我们称之为显式 Intent。

2. 使用隐式 Intent
相比于显式 Intent,隐式 Intent 则含蓄了许多,它并不明确指出我们想要启动哪一个活
动,而是指定了一系列更为抽象的 action和 category 等信息,然后交由系统去分析这个 Intent,
并帮我们找出合适的活动去启动。这个隐式 Intent 的活动,那么目前SecondActivity 可以响应什么样的隐式 Intent ,
通过在标签下配置的内容,可以指定当前活动能够响应的 action
和 category,打开 AndroidManifest.xml,添加如下代码:

<activity android:name=".SecondActivity" >
	<intent-filter>
	<action android:name="com.example.activitytest.ACTION_START" />
	<category android:name="android.intent.category.DEFAULT" />
	</intent-filter>
</activity>

在标签中我们指明了当前活动可以响应 com.example.activitytest.ACTION_
START 这个 action,而标签则包含了一些附加信息,更精确地指明了当前的活动
能够响应的 Intent 中还可能带有的 category。只有和中的内容同时能够匹
配上 Intent 中指定的 action 和 category 时,这个活动才能响应该 Intent。
修改 FirstActivity 中按钮的点击事件,代码如下所示:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});

使用了 Intent 的另一个构造函数,直接将 action 的字符串传了进去,想要启动能够响应 com.example.activitytest.ACTION_START 这个 action 的活动。要和同时匹配上才能响应,category 这是因为 android.intent.category.DEFAULT 是一种默认的 category,在调用
startActivity()方法的时候会自动将这个 category 添加到 Intent 中。重新运行程序,在 FirstActivity 的界面点击一下按钮,你同样成功启动 SecondActivity了。不同的是,这次你是使用了隐式 Intent 的方式来启动的,说明我们在标签下配置的 action 和 category 的内容已经生效了!
每个 Intent 中只能指定一个 action,但却能指定多个 category。目前我们的 Intent 中只有
一个默认的 category,修改 FirstActivity 中按钮的点击事件,代码如下所示:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
});

可以调用 Intent 中的 addCategory()方法来添加一个 category,这里我们指定了一个自定
义的 category,值为 com.example.activitytest.MY_CATEGORY。
在 Intent 中新增了一个 category,而 SecondActivity 的标签中并没有声明可以响应这个 category,所以就出现了没有任何活动可以响应该 Intent 的情况。现在我们在中再添加一个 category 的声明,如下所示:

<activity android:name=".SecondActivity" >
	<intent-filter>
	<action android:name="com.example.activitytest.ACTION_START" />
	<category android:name="android.intent.category.DEFAULT" />
	<category android:name="com.example.activitytest.MY_CATEGORY"/>
	</intent-filter>
</activity>

再次重新运行程序,你就会发现一切都正常了。

3 .更多隐式 Intent 的用法
通过隐式 Intent 来启动活动的方法,但实际上隐式 Intent 还有更多
的内容需要你去了解,本节我们就来展开介绍一下。使用隐式 Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,使得 Android 多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要调用浏览器来打开这个网页就行了。
修改 FirstActivity 中按钮点击事件的代码,如下所示:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});

Intent 的 action 是 Intent.ACTION_VIEW,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse()方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent 的 setData()方法将这个 Uri 对象传递进去。重新运行程序,在 FirstActivity 界面点击按钮就可以看到打开了系统浏览器,setData()个方法其实并不复杂,它接收一个 Uri 对象,主要用于指定当前 Intent 正在操作的数据,而这些数据通常都是以字符串的形式传入到 Uri.parse()方法中解析产生的。此对应,我们还可以在标签中再配置一个标签,精确地指
定当前活动能够响应什么类型的数据。标签中主要可以配置以下内容。

1. android:scheme
用于指定数据的协议部分,如上例中的 http 部分。
2. android:host
用于指定数据的主机名部分,如上例中的 www.baidu.com 部分。
3. android:port
用于指定数据的端口部分,一般紧随在主机名之后。
4. android:path
用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
5. android:mimeType

用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前活动才能够响应
该 Intent。不过一般在标签中都不会指定过多的内容,如上面浏览器示例中,其实只
需要指定 android:scheme 为 http,就可以响应所有的 http 协议的 Intent 了。
为了让你能够更加直观地理解,我们来自己建立一个活动,让它也能响应打开网页的
Intent。
新建 third_layout.xml 布局文件,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical" >
	<Button
	android:id="@+id/button_3"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:text="Button 3"
/>
</LinearLayout>

然后新建活动 ThirdActivity 继承自 Activity,代码如下:

public class ThirdActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	requestWindowFeature(Window.FEATURE_NO_TITLE);
	setContentView(R.layout.third_layout);
	}
}

最后在 AndroidManifest.xml 中为 ThirdActivity 进行注册。

<activity android:name=".ThirdActivity" >
	<intent-filter>
	<action android:name="android.intent.action.VIEW" />
	<category android:name="android.intent.category.DEFAULT" />
	第一行代码——Android
	50
	<data android:scheme="http" />
	</intent-filter>
	</activity>

ThirdActivity 的 中 配 置 了 当 前 活 动 能 够 响 应 的 action 是Intent.ACTION_VIEW 的常量值,而 category 则毫无疑问指定了默认的 category 值,另外在标签中我们通过 android:scheme 指定了数据的协议必须是 http 协议,这样 ThirdActivity
应该就和浏览器一样,能够响应一个打开网页的 Intent 了。FirstActivity 的界面点击一下按钮,系统自动弹出了一个列表,显示了目前能够响应这个 Intent 的所有程序。点击 Browser 还会像之前一样打开浏览器,并显示百度的主页,tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
	Intent intent = new Intent(Intent.ACTION_DIAL);
	intent.setData(Uri.parse("tel:10086"));
	startActivity(intent);
	}	
});

指定了 Intent 的 action 是 Intent.ACTION_DIAL,这又是一个 Android 系统的内置动
作。
4 向下一个活动传递数据
经过前面几节的学习,你已经对 Intent 有了一定的了解。不过到目前为止,我们都只是
简单地使用 Intent 来启动一个活动,其实 Intent 还可以在启动活动的时候传递数据的,我们
来一起看一下。在启动活动时传递数据的思路很简单,Intent 中提供了一系列 putExtra()方法的重载,可以把我们想要传递的数据暂存在 Intent 中,启动了另一个活动后,只需要把这些数据再从
Intent 中取出就可以了。比如说 FirstActivity 中有一个字符串,现在想把这个字符串传递到
SecondActivity 中,你就可以这样编写:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
}
});

这里我们还是使用显式 Intent 的方式来启动 SecondActivity,并通过 putExtra()方法传递
了一个字符串。注意这里 putExtra()方法接收两个参数,第一个参数是键,用于后面从 Intent
中取值,第二个参数才是真正要传递的数据。
然后我们在 SecondActivity 中将传递的数据取出,并打印出来,代码如下所示:

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", data);
}
}

首先可以通过 getIntent()方法获取到用于启动 SecondActivity 的 Intent,然后调用
getStringExtra()方法,传入相应的键值,就可以得到传递的数据了。这里由于我们传递的是
字符串,所以使用 getStringExtra()方法来获取传递的数据,如果传递的是整型数据,则使用
getIntExtra()方法,传递的是布尔型数据,则使用 getBooleanExtra()方法,以此类推。
重新运行程序,在 FirstActivity 的界面点击一下按钮会跳转到 SecondActivity,查看

可以看到,我们在 SecondActivity 中成功得到了从 FirstActivity 传递过来的数据。
5 返回数据给上一个活动
既然可以传递数据给下一个活动,那么能不能够返回数据给上一个活动呢?答案是肯定
的。不过不同的是,返回上一个活动只需要按一下 Back 键就可以了,并没有一个用于启动
活动 Intent 来传递数据。通过查阅文档你会发现,Activity 中还有一个 startActivityForResult()
方法也是用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活
动。毫无疑问,这就是我们所需要的。
startActivityForResult()方法接收两个参数,第一个参数还是 Intent,第二个参数是请求
码,用于在之后的回调中判断数据的来源。我们还是来实战一下,修改 FirstActivity 中按钮
的点击事件,代码如下所示:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
}
});

这里我们使用了 startActivityForResult()方法来启动 SecondActivity,请求码只要是一个
唯一值就可以了,这里传入了 1。接下来我们在 SecondActivity 中给按钮注册点击事件,并
在点击事件中添加返回数据的逻辑,代码如下所示:

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
});


}
}

构建了一个 Intent,只不过这个 Intent 仅仅是用于传递数据而已,它没有指定任何的“意图”。紧接着把要传递的数据存放在 Intent 中,然后调用了 setResult()方法。这个方法非常重要,是专门用于向上一个活动返回数据的。setResult()方法接收两个参数 ,第 一个 参数 用于 向上一 个活 动返 回处 理结果 ,一 般只 使用 RESULT_OK 或RESULT_CANCELED 这两个值,第二个参数则是把带有数据的 Intent 传递回去,然后调用了 finish()方法来销毁当前活动。
由于我们是使用 startActivityForResult()方法来启动 SecondActivity 的,在 SecondActivity
被销毁之后会回调上一个活动的 onActivityResult()方法,需要在 FirstActivity 中重
写这个方法来得到返回的数据,如下所示:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}

onActivityResult()方法带有三个参数,第一个参数 requestCode,即我们在启动活动时传
入的请求码。第二个参数 resultCode,即我们在返回数据时传入的处理结果。第三个参数 data,
即携带着返回数据的 Intent。由于在一个活动中有可能调用 startActivityForResult()方法去启
动很多不同的活动,每一个活动返回的数据都会回调到 onActivityResult()这个方法中,因此
我 们 首 先 要 做 的 就 是 通 过 检 查 requestCode 的 值 来 判 断 数 据 来 源 。 确 定 数 据 是 从

通过重写 onBackPressed()方法来解决这个问题,代码如下所示:

@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}

按下 Back 键,就会去执行 onBackPressed()方法中的代码,这
里添加返回数据的逻辑就行了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值