Intent 传递数据

本文探讨了为何在Android中使用Intent传递数据,强调其复用性和解耦性,以及在进程间通信中的作用。详细解释了Intent如何通过Parcelable接口实现跨进程数据传输,指出虽然Serializable接口也能用于数据传输,但性能不及Parcelable。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要用 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 序列化的性能。具体请点击查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值