Android项目中如何利用Intent传递数据
Android项目中如何利用Intent传递数据?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
Intent是什么
public class Intent implements Parcelable, Cloneable
上面是Intent类的完整声明,可以知道它实现了Parcelable接口。Parcelable接口是什么呢?这东西是Android上专门用来对数据进行序列化的,并且在跨进程通讯时Parceable对象是可以直接传输的。
接下来我们来看看将数据放入Intent的时,做了哪些处理。
以String为例,先看putExtra方法的代码
public Intent putExtra(String name, String value) { if (mExtras == null) { mExtras = new Bundle(); } mExtras.putString(name, value); return this; }
很简单,就是将数据放入mExtras这个Bundle对象中,顺便说一句Bundle类也实现了Parcelable接口。继续往下跟代码
public void putString(@Nullable String key, @Nullable String value) { unparcel(); mMap.put(key, value); }
内部就是将数据放入一个Map中保存。到这里数据放入Intent的过程就完成了,实际上就是Intent中有一个Bundle对象,而这个Bundle对象中又有一个Map,然后数据就保存在这里。至于那个unparcel()方法与我们的分析过程无关,有兴趣的读者可以去研究一下。
然后,我们再看取数据的过程。
继续以String作为例子,看Intent中的代码
public String getStringExtra(String name) { return mExtras == null ? null : mExtras.getString(name); }
mExtras应该很熟悉了,这是个Bundle对象,刚刚保存数据的时候就是把数据保存在它里面的。再看它的getString方法
public String getString(@Nullable String key) { unparcel(); final Object o = mMap.get(key); try { return (String) o; } catch (ClassCastException e) { typeWarning(key, o, "String", e); return null; } }
就是直接从Map里面拿出我们之前保存的String,try语句只是在验证取出的数据是否为String类型。
那照这么分析的话,两个Activity中的对象应该就是同一个对象才对啊!!为什么又说不是同一个对象呢?
为什么不是同一个对象?
如果你在putExtra之后,马上又getExtra出来,那么你取出来的对象肯定是同一个对象,这个没错!
但是这里我们要注意两点:
1.Intent中允许保存的数据类型是有限制的,准确的说是Bundle的限制,因为实质上数据是保存在Bundle中。如果我们要保存自己定义的对象,那么我们的对象必须实现了Parcelable接口或者Serializable接口。
2.我们使用Intent的方式,基本都是在一个Activity中存入,然后从另一个Activity中取出。
那么问题很明显就出在Activity的启动过程了。详细的启动过程大家可以参考老罗的文章Activity启动过程。
这里大概说一下,首先我们的app运行在app自己的进程appProcess中,然后系统在启动的时候会启动一个系统进程systemProcess。而在Activity启动时,需要向一个叫做ActivityManagerService的系统服务去注册,这样我们的Activity才能有生命周期的回调。这个ActivityManagerService服务就运行在systemProcess中。注册完之后,再回到appProcess中,完成新Activity的启动。在这个注册过程中,我们的intent是全程参与的。
说到这里就明白了,当我们调用startActivity(intent)启动另外的Activity的时候,我们的intent已经完成了两次跨进程通信,而它里面的对象已经经历了两轮序列化和反序列化,肯定不可能是同一个对象了。
这里顺便说一个问题:为什么Serializable也可以跨进程传输?
熟悉AIDL的同学都很清楚,AIDL跨进程通信支持的数据类型是:
- Java 的原生类型,如int,boolean,long,float…
- String 和CharSequence
- List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型
- AIDL 自动生成的接口 需要导入(import)
- 实现android.os.Parcelable 接口的类. 需要导入(import)。
这里并不包括Serializable类型。
关于Android项目中如何利用Intent传递数据问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。