文章目录
1)使用显式Intent在活动之间穿梭
从MainActivity 跳到 SecondActivity :
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
2)使用隐式Intent在活动之间穿梭
不明确指出启动哪个活动,而是指定一系列更为抽象的action、category等信息,然后交由系统去分析这个Intent,找出合适的活动去启动。
在创建一个Empty Activity后,在默认情况下,会在清单文件中添加的配置如下:
<activity android:name=".SecondActivity"></activity>
a) 使用默认的category
对其进行修改如下:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.intenttest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
在 <action> 标签中指明当前活动可以响应 com.example.intenttest.ACTION_START 这个action,<category>标签则包含了一些附加信息,更准确指明了当前的活动能够响应的Intent中还可能带有的category;
只有 <action>和<category>同时匹配intent中指定的action和category时,才能响应该Intent.
这里添加的category是一个默认的的category,在调用startActivity方法时自动将这个category添加到category中。
进行跳转:
Intent intent = new Intent("com.example.intenttest.ACTION_START");
startActivity(intent);
b) 指定category
每个Intent只能指定一个action,但却能指定多个category,之前是设置的默认的category,再进行设置一个。
在清单文件中添加对应的category:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.intenttest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.intenttest.MY_CATEGORY" />
</intent-filter>
</activity>
指定对应的category:
Intent intent = new Intent("com.example.intenttest.ACTION_START");
intent.addCategory("com.example.intenttest.MY_CATEGORY");
startActivity(intent);
如果清单文件和intent中category不匹配,就会崩溃掉!
3)隐式Intent调用系统应用
a) 使用系统浏览器打开网页
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
指定action为Intent.ACTION_VIEW,这是Android系统内置的动作,其常量值为:android.intent.action.VIEW ,通过Uri.parse方法,将一个网址字符串解析成Uri对象,再调用Intent的setData方法将这个Uri对象传进去。
setData接收Uri对象,用于指定当前Intent正在操作的数据,这些数据以字符串的形式传入到Uri.parse方法解析产生。
<intent-filter>中可以配置 <data>标签,用于指定但前活动能够响应什么类型的数据:
- | 描述 |
---|---|
android:scheme | 数据协议,如上面的http部分 |
android:host | 数据的主机名 |
android:port | 数据的端口 |
android:path | 指定主机名和和端口之后的部分,如一段网站中跟在域名之后的部分 |
android:mimeType | 处理的数据类型,允许使用通配符的方式指定 |
<data>标签指定的内容和Intent中携带的data完全一致时,当前活动才能响应Intent。
在清单文件中修改SecondActivity的配置如下:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
SecondActivity能响应Intent为android.intent.action.VIEW 即 Intent.ACTION_VIEW的,SecondActivity和浏览器一样能够响应一个打开网页的Intent。
b) 使用系统的拨打电话
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
4)使用Intent向下一个活动传递数据
a) 传递字符串
跳转时携带数据:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", "hello");
startActivity(intent);
获取数据:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
if (intent != null){
String data = intent.getStringExtra("extra_data");
if (!TextUtils.isEmpty(data)){
Log.d("AAAAAAAAAAA", data);
}
}
}
}
getIntent()可以获取到用于启动SecondActivity 的Intent,然后调用getStringExtra方法,传入键值得到传递的数据。
b) 传递int
携带的数据:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", 123456);
startActivity(intent);
获取数据:
Intent intent = getIntent();
if (intent != null){
int data = intent.getIntExtra("extra_data", 0);
Log.d("AAAAAA", "extra_data 为:"+data);
}
c) 传递图片
携带的数据:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", R.mipmap.ic_launcher);
startActivity(intent);
获取数据:
Intent intent = getIntent();
if (intent != null){
int data = intent.getIntExtra("extra_data", 0);
if (data != 0){
Log.d("AAAAAA", "extra_data 为:"+data);
ImageView test_iv = findViewById(R.id.test_iv);
test_iv.setImageDrawable(getResources().getDrawable(data));
}
}
d) 通过bundle传递数据
携带的数据:
Bundle bundle = new Bundle();
bundle.putString("bundleData", "helloWorld");
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", bundle);
startActivity(intent);
获取数据:
Intent intent = getIntent();
if (intent != null){
Bundle bundle = intent.getBundleExtra("extra_data");
String bundleData = bundle.getString("bundleData");
Log.d("AAAAAA", "bundleData 为:"+bundleData);
}
e) 通过serializable传递数据
Person类:
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
携带的数据:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", new Person("zhangSan", 21));
startActivity(intent);
获取数据:
Intent intent = getIntent();
if (intent != null){
Person person = (Person) intent.getSerializableExtra("extra_data");
Log.d("AAAAAA", person.getName() + " - "+person.getAge());
}
f) 通过Parcelable传递数据
Parcelable比serializable性能高,serializable是IO流的方式存储到磁盘,Parcelable是C++对象指针挪动保存数据。
Person类:
public class Person implements Parcelable {
private String name;
private int age;
public Person(){}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(Parcel in){
name = in.readString();
age = in.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeInt(age);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
携带的数据:
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("zhangSan", 21));
list.add(new Person("LiSi", 22));
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("extra_data", list);
startActivity(intent);
获取数据:
Intent intent = getIntent();
if (intent != null){
ArrayList<Parcelable> extra_data = intent.getParcelableArrayListExtra("extra_data");
for (int i=0; i < extra_data.size(); i++ ){
Person person = (Person)extra_data.get(i);
Log.d("AAAAAA", person.getName() + " - "+person.getAge());
}
}
5)返回数据给上一个Intent
第一个Activity跳转到第二个Activity再返回数据回来;
第一个Activity:
startActivityForResult方法接收两个参数,第一个是intent,第二个是请求码,用于之后的回调中判断数据的来源;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button test1_bt = findViewById(R.id.test1_bt);
test1_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
if (data != null) {
Boolean flag = data.getBooleanExtra("extra_data", false);
Log.d("AAAAAAAAAAAA", " " + flag);
}
}
break;
default:
}
}
}
第二个Activity:
设置数据并结束当前活动返回上一个活动;
setResult接收两个参数,第一个参数用于向上一个活动返回处理结果,一般只使用RESULT_OK、RESULT_CANCELED,第二个参数把数据转过去; finish销毁当前活动。
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = new Intent();
intent.putExtra("extra_data", true); // Boolean
setResult(RESULT_OK, intent);
finish();
}
}
6)标记位 flag
Intent.FLAG_ACTIVITY_NEW_TASK
如在一个应用中,当前栈为:ABC,在此基础上启动活动 B 的 intent设置为FLAG_ACTIVITY_NEW_TASK,栈就为:ABCB,和设置启动模式为 standard 一样的效果。
Intent.FLAG_ACTIVITY_CLEAR_TASK
启动新的活动前,清除之前旧的活动。与Intent.FLAG_ACTIVITY_NEW_TASK一起使用才有效果!
如一个应用中,当前栈为:AB,在此基础上启动新活动C 的intent设置为 FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK,跳转后,栈为:C,此时按下返回键,即可退出应用。
Intent intent = new Intent(SecondActivity.this, ThirdActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Intent.FLAG_ACTIVITY_CLEAR_TOP
当启动的活动,在栈中已经存在,清除在它之上的其它活动;
如栈为:ABC,此时启动活动B,清除活动C,当前栈为:AB
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
将启动的活动,放于栈顶;
如栈为:ABC,启动活动B,此时栈就变为:ACB。
可以看下这个博文:活动启动模式