上一篇:Android入门(4):Toast、Menu使用及活动的销毁
Intent是什么
各个活动通过Intent可以紧密的联系起来,Intent是Android程序中个组件进行交互的一种重要方式,不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务以及发送广播等场景。
Intent大致可以分为显式Intent和隐式Intent
创建第二个活动
我们再新建一个活动,这次我们勾选Generate Layout File
我们修改一下布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 2"
/>
</LinearLayout>
as生成的SecondActivity代码暂时可以不用修改,同时as还为我们在AndroidManifest.xml文件注册了该活动。
显式Intent
Intent有多个构造函数的重载,其中一个是Intent(Context packageContext, Class<?> cls). 这个构造函数接受两个参数,第一个参数Context要求提供一个启动活动的上下文,第二个参数Class则是指定想要启动的目标活动,通过这个构造函数就可以构建出Intent的“意图”。然后我们应该怎么使用这个Intent呢?Activity类中提供了一个startActivity()方法,这个方法是专门用于启动活动的,它接收一个Intent参数,这里我们将构建好的Intent传入startActivity()方法就可以启动目标活动了。
修改button1的功能
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,
SecondActivity.class);
startActivity(intent);
}
当点击button1就启动了SecondActivity,如果想返回上一个活动,只需back即可销毁当前活动。使用这种方式来启动活动,Intent的“意图”非常明显,因此我们称之为显式Intent。
隐式Intent
隐式Intent并不明确指出我们想要启动哪个活动,而是指定了一些列更为抽象的action和category等信息,然后由系统去分析这个Intent,并帮我们找出合适的活动去启动。
什么是合适的活动呢?简单来说就是可以相应这个隐式Intent的活动,那么目前SecondActivity可以响应什么样的隐式Intent呢?暂时,好像什么都响应不了。
通过在activity标签下配置intent-filter的内容,可以指定当前活动能够响应的action和category,打开AndroidManifest,添加如下代码:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
只有当action和category中的内容同时匹配,这个SecondActivity才能响应Intent,注意这里category使用一种默认的category,在调用startActivity方法时会自动将这个category添加到Intent中。
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
我们通过上述代码进行调用。
每个Intent中只能指定一个action,但却能指定多个category。我们尝试添加一个category:在AndroidManifest中添加<category android:name="com.example.activitytest.MY_CATEGORY"></category>
→在上述代码3行后添加intent.addCategory("com.example.activitytest.MY_CATEGORY");
即可
example
尝试使用隐式Intent打开百度
@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_VIEW,这是一个Android系统内置的动作,setData方法接受一个Uri对象,主要用于指定当前Intent正在操作的数据,而这些数据通常都是以字符串的形式传入Uri.parse()方法中解析产生的。
与此对应,我们还可以在intent-filter标签中配置一个data标签:
- android:scheme。用于指定数据的协议部分,如http
- android:host。
- android:port。
- android:path。路由
- android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
注意:只用data标签中指定的内容与Intent中携带的Data完全一致时,当前活动才能够响应,但当data标签只是指定了http,则可以响应所有的http协议的Intent。
我们再次新建一个活动ThirdActivity,在AndroidManifest中写入:
注意爆红是因为逻辑上没有检测是否安装Chrome,所以这里我们使用安装了的模拟器运行运行结果如图所示:
这里选择我们要打开的应用。
除了http协议外,我们还可以指定很多其它协议,比如geo表示显示地理位置、tel表示拨打电话
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
活动之间数据的传输
1. 向下一个活动传递数据
在启动活动时传递数据的思路很简单,Intent中提供了一系列putExtra()方法的重载,可以把我们想要传递的数据暂存在Intent中,启动了另一个活动后,只需把这些数据再从Intent中取出就可以了。类似于键值对的形式
在FirstActivity中存入data
@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);
}
在SecondActivity取出data
public class SecondActivity extends AppCompatActivity {
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d(TAG, "onCreate: "+data);
}
}
2. 返回数据给上一个活动
返回貌似是没有Intent来启动活动。其实,Activity中还有一个startActivityForResult()方法也是用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活动。
startActivityForResult方法接受两个参数,第一个参数还是Intent,第二参数是请求码,用于在之后的回调中判断数据的来源。
在FirstActivity中使用startActivityForResult启动第二个活动:
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
}
因为待会有一个函数在第一个活动中接受所有返回的数据,所以需要一个requestCode来判断是哪个活动发送来的,这里1标识着第二个活动
在第二个活动设定返回数据:
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
});
通过setResult方法设定返回数据,第一个参数为resultCode,一般为RESULT_OK或RESULT_CANCELED,用于对返回结果的处理。
在第一个活动中重写onActivityResult方法来接受和处理返回的数据:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode) {
case 1:
if(resultCode == RESULT_OK) {
String res = data.getStringExtra("data_return");
Log.d(TAG, "onActivityResult: "+res);
}
break;
default:
}
}
点击button1→点击button2,打印出:
若是通过back返回的话我们只需重写onBackPressed()方法即可
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}