android ——Intent

Intent是android程序中各组件之间进行交互的重要方式,它可以用于指明当前组件想要执行的动作,也可以在不同组件之间传递数据,Intent一般被用于启动活动,启动服务以及发送广播。

一、显式的使用Intent启动活动

Intent有多个构造函数的重载,其中有Intent(Context packageContext, Class<?>cls ),第一个参数Context指定了启动活动的上下文,第二个参数指定了想要启动的目标活动

Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);

先创建一个Intent对象,指定想要启动的目标活动,然后调用startActivity()方法根据参数intent对象启动这个活动。

二、隐式的使用Intent启动活动

隐式Intent它并不明确的指示想要启动那一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent再去启动合适的活动

先创建一个自定义action和category的活动在AndroidManifest中:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xbt.exp19">

    <application
...
        </activity>
        <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="XX"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

这里随意设定了XXv这个action,然后android.intent.category.DEFAULT是一种默认的category,所以调用的时候:

  Intent intent = new Intent("XX");
  startActivity(intent);

Intent的参数就是一个XX的字符串,指定了想要启动的活动的action信息,然后startActivity()方法会自动的把默认的category信息添加到intent中

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xbt.exp19">

    <application
...
        </activity>
        <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="XX"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="ww"/>
                <category android:name="xw"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

这里额外添加了两个category,因为category是可以增加任意多个的,然后使用的时候:

  Intent intent = new Intent("XX");
  intent.addCategory("ww");
  intent.addCategory("xw");
  startActivity(intent);

这样使用就行,要注意的地方有:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xbt.exp19">

    <application
...
        </activity>
        <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="XX"/>
                <category android:name="ww"/>
                <category android:name="xw"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

这样就会出错,因为startActivity()方法会自动的把默认的category信息添加到intent中所以category默认的那一个信息必须得加上,,不过我没查过资料,,反正我手机必须加上。。

然后使用一下系统设定的action:

  Intent intent1 = new Intent(Intent.ACTION_VIEW);
  intent1.setData(Uri.parse("http://www.baidu.com"));
   startActivity(intent1);

这样就能启动浏览器,并打开百度。

 Intent intent2 = new Intent(Intent.ACTION_DIAL);
 intent2.setData(Uri.parse("tel:10086"));
startActivity(intent2);

这样就能打开拨号盘,并且已经输入好10086。

三、使用Intent传递数据

1、向下一个活动传递数据

  Intent intent = new Intent(MainActivity.this,Main2Activity.class); 
  intent.putExtra("id",1); 
  intent.putExtra("name","名字");  
  intent.putExtra("age",20.5f); 
  startActivity(intent); 

接收的时候:

  Intent intent = getIntent();
  String name = intent.getStringExtra("name");
  int id =intent.getIntExtra("id");
  float age = intent.getFloatExtra("age");

发送的时候使用的putExtra()第一个参数相当于发送的数据的键,第二个参数是发送的实际值,接受的时候就是根据这个键,然后相应的类型要使用不同的方法接收数据。

2、返回数据给上一个活动

a、主活动中创建用于启动目标活动的Intent对象。

b、调用startActivityForResult()方法启动目标活动。

c、被启动的活动创建一个Intent对象,并调用putExtra()方法将要传递的数据存放在intent中。

d、调用setResult()方法返回数据,然后调用finish()销毁该活动。

e、在主活动中重写onActivityResult()方法,在其中保存接受到的数据

主活动中的启动目标活动的代码:

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

startActivityForResult()的第二个参数是一个请求码,要求是一个唯一值。

被启动的活动中的返回数据的代码:

button2.setOnClickListener(new View.OnClickListener(){
    public void onClick(View v){
        Intent intent = new Intent();
        intent.putExtra("data_return","first");
        setResult(RESULT_OK,intent);
        finish();
    }
});

setResult()方法第一个参数用于向上一个活动返回处理结果,一般使用RESULT_OK或RESULT_CANCELED两个值,第二个参数把带有数据的Intent传递出去。

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

由于我们使用的startActivityForResult方法来启动SecondActivity的,在SecondActivity销毁后会回调上一个的onActivityResult方法,因此就需要重写这个方法

onActivityResult有三个参数,第一个参数是我们启动活动时传入的请求码,第二个参数resultCode即我们返回数据时传入的处理结果,第三个参量,即携带着返回数据的Intent。

在一个活动中我们可能利用startActivityForResult启动很多不同的活动,每一个返回的数据都会回调到onActivityResult这个方法中,我们首先要检查的就是requestCode的值来判断数据来源,再通过resultCode检查处理结果是否成功。

四、使用Intent传递对象

想要使用使用Intent传递对象就是要把对象序列化,变得可存储可传输的状态然后才能使用Intenti传输,目前有Serializable 和Parcelable两种方式,Serializable相对Parcelable实现简单,但是效率低一些。

Serializable:

假如有这样一个Fruit对象把它序列化:

 1 public class Fruit implements Serializable {
 2     private String name;
 3 
 4     private int imageId;
 5 
 6     public Fruit(String name,int imageId){
 7         this.name = name;
 8         this.imageId = imageId;
 9     }
10 
11     public String getName(){
12         return name;
13     }
14 
15     public int getImageId(){
16         return imageId;
17     }
18 }

然后在活动中传递的时候:

  Fruit fruit = new Fruit("orange",1)  
  Intent intent = new Intent(MainActivity.this,Main2Activity.class); 
  intent.putExtra("fruit",fruit); 
  startActivity(intent); 

在目标活动中:

  Fruit fruit = (Fruit) getIntent().getSerializableExtra("fruit");

Parcelable:

这个就比较复杂了需要对整个对象进行分解

比如这样一个Fruit对象把它序列化

public class Fruit implements Parcelable {
    private String name;

    private int imageId;
    
    public String getName(){
        return name;
    }

    public int getImageId(){
        return imageId;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(imageId);
    }
    
    public static final Parcelable.Creator<Fruit> CREATOR = new Parcelable.Creator<Fruit>(){
        @Override
        public Fruit createFromParcel(Parcel parcel) {
            Fruit fruit = new Fruit();
            fruit.name = parcel.readString();
            fruit.imageId = parcel.readInt();
            return fruit;
        }

        @Override
        public Fruit[] newArray(int i) {
            return new Fruit[i];
        }
    };
}

重写describeContents()和writeToParcel()这两个方法。其中describeContents()方法直接返回0 就可以了,而writeToParcel()方法中我们需要调用Parcel的writeXxx()方法将Person 类中的字段一一写出。

还必须在Person 类中提供一个名为CREATOR 的常量,接着需要重写createFromParcel()和newArray()这两个方法,在createFromParcel()方法中我们要去读取刚才写出的name 和Id字段,并创建一个fruit对象进行返回,其中name 和Id都是调用Parcel 的readXxx()方法读取到的,注意这里读取的顺序一定要和刚才写出的顺序完全相同。而newArray()方法中的实现就简单多了,只需要new 出一个Fruit数组,并使用方法中传入的size 作为数组大小就可以了。

目标活动中这样写:

Fruit fruit = (Fruit) getIntent().getParcelableArrayExtra("fruit");
原文地址:https://www.cnblogs.com/xxbbtt/p/7488130.html