Intent 传递数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31876841/article/details/78382802

为什么要用 Intent 传递数据

当我们想要在两个 Activity 间传递数据时,我们会很自然的想到要用 Intent 的 putExtra 方法来传递数据。但是为什么一定要用 Intent 传递数据呢?

1. 复用性强、解耦

我们会发现,intent 在很多的组件中都出现过。如,启动 Activity, 启动服务, 传递广播。我们会经常性的利用 Intent 在这些组件之间传递信息,进行通信。所以,高度的复用性,和简便的使用方法,使 Activity 间解耦,肯定是我们使用它的理由。

2. 进程间通信

在启动 Activity 的时候,是需要通过系统服务 AMS(ActivityManagerService)注册,才能有生命周期的回调的,在这一过程中,intent 是全程参与的,所以在启动 Activity 的过程中,intent 已经跨越两次进程了。而且,我们创建 Activity 时候,是可以创建一个运行在新进程的 Activity 的。并且,我们也可以利用 intent 启动一些系统软件。上述这些操作,全都是跨进程通信的,Intent 就具有这样的能力。这也是我们使用 Intent 的一个原因。具体Activity启动过程

进程-分割多道程序,避免在内存并发执行时出乱子。在不同进程间内存是不共享的。

怎么传输的

上一节,我们说过,启动 Acitvity 时是要跨进程的,所以问题就变成了如何跨进程通信。在 Android 中我们是通过 AIDL 来实现的。而 AIDL 跨进程通信只支持的数据类型是:
1. Java 的原生类型,如int,boolean,long,float…
2. String 和CharSequence
3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型
4. AIDL 自动生成的接口 需要导入(import)
5. 实现android.os.Parcelable 接口的类. 需要导入(import)。

那么 Intent 是怎么实现的呢,我们一起来看一下:

public class Intent implements Parcelable, Cloneable 

原来是实现了 Parcelable 接口。我们再往下看一下,稍后再来谈一下 Parcelable 。

    public Intent putExtra(String name, String value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putString(name, value);
        return this;
    }

哦哦,原来数据都是放到 Bundle 中的。

public final class Bundle extends BaseBundle implements Cloneable, Parcelable
    public static final Bundle EMPTY;

    static {
        EMPTY = new Bundle();
        EMPTY.mMap = ArrayMap.EMPTY;
    }
    public void putString(@Nullable String key, @Nullable String value) {
        unparcel();
        mMap.put(key, value);
    }

Bundle 中也实现了 Parcleable
,而且用的是 Map 用来装载数据的。

Parcelable

Parcel 提供了一套机制,可以将序列化之后的数据写到一个共享内存当中,其他进程可以通过这块共享区读出数据并反序列话成对象。

进程间的数据传递是通过其中的内存共享区来实现的

下面我们就来实现通过 intent 来传递对象:

public class Usr implements Parcelable {
    private String name;
    private int age;

    public Usr() {
    }

    protected Usr(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    //读取接口
    public static final Creator<Usr> CREATOR = new Creator<Usr>() {
        @Override
        public Usr createFromParcel(Parcel in) {
            return new Usr(in);
        }

        @Override
        public Usr[] newArray(int size) {
            return new Usr[size];
        }
    };

    //内容描述接口
    @Override
    public int describeContents() {
        return 0;
    }
    //写入接口函数,打包
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
}

我们实现 Parcelable 接口,重写其中的方法,就可以了。在 Android Studio 中实现起来其实是很方便的。

  Usr usr = new Usr();
  intent.putExtra("usr", usr);

  Usr usr = getIntent().getParcelableExtra("usr");

最后,在 ActivityManagerNative 的 startActivity 中执行 Intent 的 writeToParcel 方法。

 public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
       .
       .

        intent.writeToParcel(data, 0);
       .
       .
    }

这样就完成了对象的传递。

Serializable

其实通过 Java 自带的接口实现序列化后也是可以添加到 intent 当中,进行传输的。不过,虽然实现起来方便,但是性能却比不上 Parcel。但是,我们可以自己重写 writeObject 方法,这样就能提升 Serializable 序列化的性能。具体请点击查看

猜你喜欢

转载自blog.csdn.net/qq_31876841/article/details/78382802