Android  Intent传递数据底层分析详细介绍

Android  Intent传递数据底层分析详细介绍

我们知道在Activity切换时,如果需要向下一个ActivityB传递数据,可以借助Intent对象的putExtra方法。

但是不知各位有没有想过这样一个问题:ActivityB中获取到的对象跟上一个Activity中的那个对象有什么关系?

换句话说就是,我在ActivityB中通过Intent获取的对象跟ActivityA中的那个对象,有没有可能是同一个对象?

按照常理来说,博主提出一个设想后续的就是证明过程了,但是我要遗憾的告诉你,这里并非是同一个对象。(PS:废话,如果是同一个对象,那还有EventBus这些东西什么事儿 T_T)

那么问题又来了,这两个Activity都在同一个进程里面,甚至都在同一个线程里面,数据本来就是可以共享的,为什么从一个Activity传到另一个Activity之后,就不是一个对象了呢?它从什么时候变成另外的对象的呢?

不着急,且听我慢慢道来。

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类型。

于是去看了源码,发现是Parcel自己对Serializable类型的对象做了兼容,可以直接写入其中。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android 通过Intent使用Bundle传递对象详细介绍

    Android 通过Intent使用Bundle传递对象 Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法. 被传递的对象需要先实现序列化,而序列化对象有两种方式:java.io.Serializable和android.os.Parcelable Java中使用的是Serializable,而谷歌在Android使用了自定义的Parcelable. 两种序列化方式的区别: 1.在使用内存的时候,Parcelable比Serializa

  • Android Activity中使用Intent实现页面跳转与参数传递的方法

    本文实例讲述了Android Activity中使用Intent实现页面跳转与参数传递的方法.分享给大家供大家参考,具体如下: 新建一个FirstAvtivity.java package com.zhuguangwei; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.O

  • Android利用Intent实现记事本功能(NotePad)

    本文实例为大家分享了Intent如何实现一个简单的记事本功能的演示过程,供大家参考,具体内容如下 1.运行截图 单击右上角[-]会弹出[添加]菜单项,长按某条记录会弹出快捷菜单[删除]项. 2.主要设计步骤 (1)添加引用 鼠标右击[引用]à[添加引用],在弹出的窗口中勾选"System.Data"和"System.Data.SQlite",如下图所示: 注意:不需要通过NuGet添加SQLite程序包,只需要按这种方式添加即可. (2)添加图片 到Android

  • Android实现打开各种文件的intent方法小结

    本文实例讲述了Android实现打开各种文件的intent方法.分享给大家供大家参考,具体如下: import android.app.Activity; import Android.content.Intent; import android.net.Uri; import android.net.Uri.Builder; import Java.io.File; import android.content.Intent; //自定义android Intent类, //可用于获取打开以下

  • Android使用Intent发送短信的实现方法

    本文实例讲述了Android使用Intent发送短信的实现方法.分享给大家供大家参考,具体如下: 在一个Activity中使用Intent发送短信 package com.zhuguangwei; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.

  • Android中Intent传递对象的3种方式详解

    前言 相信Intent的用法大家已经比较熟悉了,Intent可以用来启动Activity,Service等等,同时我们也可以通过Intent来进行传递数据,当我们使用Intent在Activity 间传递信息时发现putExtra() 方法并不支持自定义对象的传输,下面就来介绍三种解决方式. 一.Serializable 方式 这是最简单的一种方法,因为我们要做的就是让我们自定义的对象实现 Serializable 这个空接口. public class Person implements Se

  • Android开发中Intent用法总结

    本文实例讲述了Android开发中Intent用法.分享给大家供大家参考,具体如下: Android手机软件开发中,Intent作为手机软件开发时很重要的对象需要引起我们的重视,实际上,intent也是体现Android开发具有其独特性的一个标志性的对象. 当一个Activity要启动另外一个Activity的时候,也许一个以前较为熟悉的模式是:调用一个new函数,直接创建具有窗口特征类的对象,又或者直接调用一个启动函数来启动.这种方式简洁.明了,但是却违背了Android开发的理念.Andro

  • Android Activity与Intent详解及示例代码

    Android有三个基础组件Activity,Service和BroadcastReceiver,他们都是依赖Intent来启动.本文介绍的是Activity的生命周期以及针对Activity的Intent使用. 之前的例子一直都是使用Activity,在一个Layout XML与一个Activity捆绑的情况下可以视为一个Form,多个Layout XML与一个Activity捆绑的话那就是个Application本身了.Intent可以分为显式Intent和隐式Intent:显式Intent

  • Android常用的intent action汇总

    本文总结讲述了Android常用的intent action功能.分享给大家供大家参考,具体如下: Android基本的设计理念是鼓励减少组件间的耦合,因此Android提供了Intent (意图) ,Intent提供了一种通用的消息系统,它允许在你的应用程序与其它的应用程序间传递Intent来执行动作和产生事件.Intent作为联系各Activity之间的纽带,其作用并不仅仅只限于简单的数据传递.通过其自带的属性,其实可以方便的完成很多较为复杂的操作.例如直接调用拨号功能.处理接收短信,诸如此

  • Android Intent传递数据底层分析详细介绍

    Android  Intent传递数据底层分析详细介绍 我们知道在Activity切换时,如果需要向下一个ActivityB传递数据,可以借助Intent对象的putExtra方法. 但是不知各位有没有想过这样一个问题:ActivityB中获取到的对象跟上一个Activity中的那个对象有什么关系? 换句话说就是,我在ActivityB中通过Intent获取的对象跟ActivityA中的那个对象,有没有可能是同一个对象? 按照常理来说,博主提出一个设想后续的就是证明过程了,但是我要遗憾的告诉你,

  • Android  Intent传递数据底层分析详细介绍

    Android  Intent传递数据底层分析详细介绍 我们知道在Activity切换时,如果需要向下一个ActivityB传递数据,可以借助Intent对象的putExtra方法. 但是不知各位有没有想过这样一个问题:ActivityB中获取到的对象跟上一个Activity中的那个对象有什么关系? 换句话说就是,我在ActivityB中通过Intent获取的对象跟ActivityA中的那个对象,有没有可能是同一个对象? 按照常理来说,博主提出一个设想后续的就是证明过程了,但是我要遗憾的告诉你,

  • Android Intent传递数据大小限制详解

    前言 在sendBroadcast,startActivity时,我们会用到Intent. Intent可以携带一些数据,比如基本类型数据int.Boolean,或是String,或是序列化对象,Parcelable与Serializable. Intent传递数据时,如果数据太大,可能会出现异常.比如App闪退,或是Intent发送不成功,logcat报错等等. 这就牵涉到一个问题:Intent 传递数据大小限制. Intent到底能够携带多少数据呢? 使用Intent传送数据时,可能会出现异

  • Android Intent传递对象的两种方法(Serializable,Parcelable)详细介绍

    Android Intent传递对象的两种方法(Serializable,Parcelable)详细介绍 今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是Bundle.putParcelable(Key, Object);当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口,为了让大家更容易理解我还是照常写

  • Android Intent传递大量数据出现问题解决

    目录 正文 异常TransactionTooLargeException Intent携带信息的大小受Binder限制 为什么Binder要限制传输数据的大小 替代方案 正文 官方文档 https://developer.android.google.cn/guide/components/activities/parcelables-and-bundles 在sendBroadcast,startActivity时,我们会用到Intent. Intent可以携带一些数据,比如基本类型数据int

  • Android 使用Intent传递数据的实现思路与代码

    Intent是Android中一个非常重要的概念,跟这个词的本意(意图,目的)一样,这个类在Android中的作用就是要调用某个组建去做某一件事,比如通过startActivity启动一个Activity,通过startService启动一个Service,通过sendBroadcast发送一个广播等,它相当于各个组建间的一个桥梁.很重要的一点是这个过程是可以跨进程的,比如在应用中可以启动调用某个播放器组件(系统自身的或者第三方的)来播放一段视频,启动照相机程序拍照等等. 当我们启动视频播放器播

  • Android内置SQLite的使用详细介绍

    目录 一.创建数据库 1.新建数据库帮助类 2.在数据库帮助类中输入代码 3.代码讲解 二.添加数据 1.界面效果 2.准备工作 3.布局界面 activity_main.xml 4.类文件代码 MainActivity.java 5.代码讲解 三.查询数据 1.界面效果图 2.布局界面 activity_second.xml 3.类文件 SecondActivity.java 4.代码讲解 四.修改数据 1.界面效果图 2.布局界面 activity_ third.xml 3.类文件 Thir

  • python+mongodb数据抓取详细介绍

    分享点干货!!! Python数据抓取分析 编程模块:requests,lxml,pymongo,time,BeautifulSoup 首先获取所有产品的分类网址: def step(): try: headers = { ..... } r = requests.get(url,headers,timeout=30) html = r.content soup = BeautifulSoup(html,"lxml") url = soup.find_all(正则表达式) for i

  • Flutter 和 Android 互相传递数据的实现

    (一)Android代码设置 1,打开Android Studio 创建一个应用程序,包名dev.android.book 2, 创建一个MyApplication ,应用在AndroidManifest.xml文件中的application的android:name属性上 3,创建FlutterEngine的实例,然后把这个实例添加到缓存的FlutterEngine当中 4,创建MethodChannel的实例,指定一个此实例的唯一字符串,例如dev.android.book/add 5, 设

  • Android webview加载H5方法详细介绍

    目录 1,安卓APP 怎么用webview加载H5 2,H5怎么调用安卓定义的方法 3,安卓怎么调用H5定义的方法 这篇文章主要阐述3个知识点 安卓APP 怎么用webview加载H5 H5怎么调用安卓定义的方法 安卓怎么调用H5定义的方法 1,安卓APP 怎么用webview加载H5 安卓端定义个webview xml 页面,代码如下所示: <?xml version="1.0" encoding="utf-8"?> <WebView xmlns

随机推荐