展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 系统应用 > 4.5.2 Intent之复杂数据的传递

4.5.2 Intent之复杂数据的传递

本节引言: 上一节已经把Intent的基础用法过了一遍,包括它的七个属性、显式Intent和隐式Intent的区别、如何自定义隐式Intent,以及一些常用的系统Intent。接下来这部分,重点就落在Intent的数据传递上了。话不多说,直接进入本节内容。 1.Intent传递简单数据 还记得我们在

本文目录

    本节引言:

    上一节已经把Intent的基础用法过了一遍,包括它的七个属性、显式Intent和隐式Intent的区别、如何自定义隐式Intent,以及一些常用的系统Intent。接下来这部分,重点就落在Intent的数据传递上了。话不多说,直接进入本节内容。

    1.Intent传递简单数据

    还记得我们在Activity那里学过如何在两个Activity中互相传递简单数据的方法吗?

    就是可以直接通过调用Intent的putExtra()方法存入数据,然后在获得Intent后调用getXxxExtra获得 对应类型的数据;传递多个的话,可以使用Bundle对象作为容器,通过调用Bundle的putXxx先将数据 存储到Bundle中,然后调用Intent的putExtras()方法将Bundle存入Intent中,然后获得Intent以后, 调用getExtras()获得Bundle容器,然后调用其getXXX获取对应的数据! 另外数据存储有点类似于Map的<键,值>!

    2.Intent传递数组

    嘿嘿,普通类型倒没问题,但是如果是数组咧?解决方法如下:

    写入数组:

    bd.putStringArray("StringArray", new String[]{"呵呵","哈哈"});
    //可把StringArray换成其他数据类型,比如int,float等等...

    读取数组:

    String[] str = bd.getStringArray("StringArray")

    3.Intent传递集合

    嗯,数组很简单吧,那我们再来传下集合~这个就稍微复杂点了,分情况处理:

    1)List<基本数据类型或String>

    写入集合:

    intent.putStringArrayListExtra(name, value)
    intent.putIntegerArrayListExtra(name, value)

    读取集合:

    intent.getStringArrayListExtra(name)
    intent.getIntegerArrayListExtra(name)

    2)List< Object>

    将list强转成Serializable类型,然后传入(可用Bundle做媒介)

    写入集合:

    putExtras(key, (Serializable)list)

    读取集合:

    (List) getIntent().getSerializable(key)
    
    

    PS:Object类需要实现Serializable接口

    3)Map,或更复杂的

    解决方法是:外层套个List

    //传递复杂些的参数 
    Map map1 = new HashMap();  
    map1.put("key1", "value1");  
    map1.put("key2", "value2");  
    List> list = new ArrayList>();  
    list.add(map1);  
    Intent intent = new Intent();  
    intent.setClass(MainActivity.this,ComplexActivity.class);  
    Bundle bundle = new Bundle();  
    //须定义一个list用于在budnle中传递需要传递的ArrayList,这个是必须要的  
    ArrayList bundlelist = new ArrayList();   
    bundlelist.add(list);   
    bundle.putParcelableArrayList("list",bundlelist);  
    intent.putExtras(bundle);                
    startActivity(intent); 
    

    4.Intent传递对象

    传递对象的方式有两种:将对象转换为Json字符串或者通过Serializable,Parcelable序列化 不建议使用Android内置的抠脚Json解析器,可使用fastjson或者Gson第三方库!

    1)将对象转换为Json字符串

    Gson解析的例子:

    Model:

    public class Book{
        private int id;
        private String title;
        //...
    }
    public class Author{
        private int id;
        private String name;
        //...
    }

    写入数据:

    Book book=new Book();
    book.setTitle("Ja va编程思想");
    Author author=new Author();
    author.setId(1);
    author.setName("Bruce Eckel");
    book.setAuthor(author);
    Intent intent=new Intent(this,SecondActivity.class);
    intent.putExtra("book",new Gson().toJson(book));
    startActivity(intent);

    读取数据:

    String bookJson=getIntent().getStringExtra("book");
    Book book=new Gson().fromJson(bookJson,Book.class);
    Log.d(TAG,"book title->"+book.getTitle());
    Log.d(TAG,"book author name->"+book.getAuthor().getName());

    2)使用Serializable,Parcelable序列化对象

    1.Serializable实现:

    ①业务Bean实现:Serializable接口,写上getter和setter方法
    ②Intent通过调用putExtra(String name, Serializable value)传入对象实例 当然对象有多个的话多个的话,我们也可以先Bundle.putSerializable(x,x);
    ③新Activity调用getSerializableExtra()方法获得对象实例: eg:Product pd = (Product) getIntent().getSerializableExtra("Product");
    ④调用对象get方法获得相应参数

    2.Parcelable实现:

    一般流程:

    ①业务Bean继承Parcelable接口,重写writeToParcel方法,将你的对象序列化为一个Parcel对象;
    ②重写describeContents方法,内容接口描述,默认返回0就可以
    ③实例化静态内部对象CREATOR实现接口Parcelable.Creator
    ④同样式通过Intent的putExtra()方法传入对象实例,当然多个对象的话,我们可以先 放到Bundle里Bundle.putParcelable(x,x),再Intent.putExtras()即可

    一些解释:

    通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射 成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面, 在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的 顺序和读的顺序必须一致。

    实现Parcelable接口的代码示例:

    //Internal Description Interface,You do not need to manage  
    @Override  
    public int describeContents() {  
         return 0;  
    }  
    @Override  
    public void writeToParcel(Parcel parcel, int flags){  
        parcel.writeString(bookName);  
        parcel.writeString(author);  
        parcel.writeInt(publishTime);  
    }  
    public static final Parcelable.Creator CREATOR = new Creator() {  
        @Override  
        public Book[] newArray(int size) {  
            return new Book[size];  
        }  
    @Override  
        public Book createFromParcel(Parcel source) {  
            Book mBook = new Book();    
            mBook.bookName = source.readString();   
            mBook.author = source.readString();    
            mBook.publishTime = source.readInt();   
            return mBook;  
        }  
    };

    Android Studio生成Parcleable插件:

    Intellij/Andriod Studio插件android-parcelable-intellij-plugin 只要ALT+Insert,即可直接生成Parcleable接口代码。

    另外:Android中大量用到Parcelable对象,实现Parcable接口又是非常繁琐的,可以用到 第三方的开源框架:Parceler,因为Ma ven的问题,暂时还没试。

    参考地址:[Android的Parcelable自动生成]

    3.两种序列化方式的比较:

    两者的比较:

    • 1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
    • 2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
    • 3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的 持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable。

    5.Intent传递Bitmap

    bitmap默认实现Parcelable接口,直接传递即可

    实现代码:

    Bitmap bitmap = null;
    Intent intent = new Intent();
    Bundle bundle = new Bundle();
    bundle.putParcelable("bitmap", bitmap);
    intent.putExtra("bundle", bundle);

    6.传来传去不方便,直接定义全局数据

    如果是传递简单的数据,有这样的需求,Activity1 -> Activity2 -> Activity3 -> Activity4, 你想在Activity中传递某个数据到Activity4中,怎么破,一个个页面传么?

    显然不科学是吧,如果你想某个数据可以在任何地方都能获取到,你就可以考虑使用 Application全局对象了!

    Android 系统在启动每个应用进程时,都会创建一个 Application 对象,而且整个应用运行期间通常只会有这一个实例。所以,从这个角度看,Application 本身就具备单例(singleton)模式的特征。它的生命周期也是应用里最长的,基本上和整个程序的生命周期保持一致。正因为如此,如果有些数据不适合只用静态值来保存——无论是固定不变的,还是后续可能会变化的——就可以考虑放到 Application 里统一管理。不过要做到这一点,前提是先自定义一个类去继承 Application,并明确告诉系统:启动时要实例化的是这个自定义的 Application,而不是系统默认的那个。具体做法,就是在 AndroidManifest.xml 的 application 标签中添加 name属性!

    关键部分代码:

    1)自定义Application类:

    class MyApp extends Application {
        private String myState;
        public String getState(){
            return myState;
        }
        public void setState(String s){
            myState = s;
        }
    }

    2)AndroidManifest.xml中声明:

    3)在需要的地方调用:

    class Blah extends Activity {
        @Override
        public void onCreate(Bundle b){
            ...
        MyApp appState = ((MyApp)getApplicationContext());
        String state = appState.getState();
            ...
        }
    }

    高逼格写法

    :在任何位置都能获取到Application全局对象。

    Applicaiton是系统的一个组件,他也有自己的一个生命周期,我们可以在onCraete里获得这个 Application对象。贴下修改后的代码吧!

    class MyApp extends Application {
        private String myState;
        private static MyApp instance;
    public static MyApp getInstance(){
            return instance;
        }
    public String getState(){
            return myState;
        }
        public void setState(String s){
            myState = s;
        }
    @Override
        public void onCreate(){
            onCreate();
            instance = this;
        }
    }

    然后在任意地方我们就可以直接调用:MyApp.getInstance()来获得Application的全局对象!

    注意事项:

    Application对象是存在于内存中的,也就有它可能会被系统杀死,比如这样的场景:

    我们在Activity1中往application中存储了用户账号,然后在Activity2中获取到用户账号,并且显示!

    如果我们点击home键,然后过了N久候,系统为了回收内存kill掉了我们的app。这个时候,我们重新 打开这个app,这个时候很神奇的,回到了Activity2的页面,但是如果这个时候你再去获取Application 里的用户账号,程序就会报NullPointerException,然后crash掉~

    之所以会发生上述crash,是因为这个Application对象是全新创建的,可能你以为App是重新启动的, 其实并不是,仅仅是创建一个新的Application,然后启动上次用户离开时的Activity,从而创造App 并没有被杀死的假象!所以如果是比较重要的数据的话,建议你还是进行本地化,另外在使用数据的时候 要对变量的值进行非空检查!还有一点就是:不止是Application变量会这样,单例对象以及公共静态变量 也会这样~

    7.单例模式传参

    上面的Application就是基于单例的,单例模式的特点就是可以保证系统中一个类有且只有一个实例。 这样很容易就能实现,在A中设置参数,在B中直接访问了。这是几种方法中效率最高的。

    范例代码:(代码来自于网上~)

    ①定义一个单例类:

    public class XclSingleton  
    {  
        //单例模式实例  
        private static XclSingleton instance = null;  
    //synchronized 用于线程安全,防止多线程同时创建实例  
        public synchronized static XclSingleton getInstance(){  
            if(instance == null){  
                instance = new XclSingleton();  
            }     
            return instance;  
        }     
    final HashMap mMap;  
        private XclSingleton()  
        {  
            mMap = new HashMap();  
        }  
    public void put(String key,Object value){  
            mMap.put(key,value);  
        }  
    public Object get(String key)  
        {  
            return mMap.get(key);  
        }  
    } 

    ②设置参数:

    XclSingleton.getInstance().put("key1", "value1");  
    XclSingleton.getInstance().put("key2", "value2");  

    本节小结:

    好的,关于Intent复杂数据传输就到这里,本节除了讲述使用Intent来传递复杂数据外,还教了大家 使用Application和单例模式来传递参数!相信会对大家在数据传递方面带来方便,谢谢~

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    系统应用
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

    网站备案号:苏ICP备2026018738号-1 联系邮箱:bd@zhengruan.com

    Copyright ©2018-2026