(转载)Android 之最新最全的Intent传递数据方法

转载于 https://www.jianshu.com/p/1169dba99261,如有任何问题请联系我!

Intent的基本使用

Android 之最新最全的Intent传递数据方法

intent传递数据

为什么要和intent单独拿出来讲,因为Intent传递数据也是非常重要的

一、简单的传递数据

二、传递数组

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

读取数组:

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

三、传递集合

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<Object>)getIntent().getSerializable(key)

PS:Object类需要实现Serializable接口

3)Map<String, Object>,或更复杂的

解决方法是:外层套个List

//传递复杂些的参数 Map<String,Object>map1=newHashMap<String,Object>();map1.put("key1","value1");map1.put("key2","value2");List<Map<String,Object>>list=newArrayList<Map<String,Object>>();list.add(map1);Intentintent=newIntent();intent.setClass(MainActivity.this,ComplexActivity.class);Bundlebundle=newBundle();//须定义一个list用于在budnle中传递需要传递的ArrayList<Object>,这个是必须要的  ArrayListbundlelist=newArrayList();bundlelist.add(list);bundle.putParcelableArrayList("list",bundlelist);intent.putExtras(bundle);startActivity(intent);

四、Intent传递对象

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

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

Gson解析的例子:

Model:

publicclassBook{privateintid;privateStringtitle;//...}publicclassAuthor{privateintid;privateStringname;//...}

写入数据:

Bookbook=newBook();book.setTitle("Java编程思想");Authorauthor=newAuthor();author.setId(1);author.setName("Bruce Eckel");book.setAuthor(author);Intentintent=newIntent(this,SecondActivity.class);intent.putExtra("book",newGson().toJson(book));startActivity(intent);

读取数据:

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

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

但是不知道你有没有发现,putExtra()方法中所支持的数据类型是有限的,虽然常用的一些数据类型它都会支持,但是当你想去传递一些自定义对象的时候就会发现无从下手。不用担心,下面我们就学习一下使用Intent 来传递对象的技巧。

方式一:Serializable 方式

Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。至于序列化的方法也很简单,只需要让一个类去实现Serializable 这个接口就可以了。

比如说有一个Person 类,其中包含了name 和age 这两个字段,想要将它序列化就可以这样写:

publicclassPersonimplementsSerializable{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}}

其中get、set 方法都是用于赋值和读取字段数据的,最重要的部分是在第一行。这里让Person 类去实现了Serializable 接口,这样所有的Person 对象就都是可序列化的了。

接下来在FirstActivity 中的写法非常简单:

Personperson=newPerson();person.setName("Tom");person.setAge(20);Intentintent=newIntent(FirstActivity.this,SecondActivity.class);intent.putExtra("person_data",person);startActivity(intent);

可以看到,这里我们创建了一个Person 的实例,然后就直接将它传入到putExtra()方法中了。由于Person 类实现了Serializable 接口,所以才可以这样写。

接下来在SecondActivity 中获取这个对象也很简单,写法如下:

Personperson=(Person)getIntent().getSerializableExtra("person_data");

方式二:Parcelable

除了Serializable 之外,使用Parcelable 也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent 所支持的数据类型,这样也就实现传递对象的功能了。

下面我们来看一下Parcelable 的实现方式,修改Person 中的代码,如下所示:

publicclassPersonimplementsParcelable{privateStringname;privateintage;@OverridepublicintdescribeContents(){// TODO Auto-generated method stub  return0;}@OverridepublicvoidwriteToParcel(Parceldest,intflags){// TODO Auto-generated method stub  dest.writeString(name);dest.writeInt(age);}publicstaticfinalParcelable.Creator<Person>CREATOR=newParcelable.Creator<Person>(){@OverridepublicPersoncreateFromParcel(Parcelsource){// TODO Auto-generated method stub  Personperson=newPerson();person.name=source.readString();person.age=source.readInt();returnperson;}@OverridepublicPerson[]newArray(intsize){// TODO Auto-generated method stub  returnnewPerson[size];}};}

Parcelable 的实现方式要稍微复杂一些。可以看到,首先我们让Person 类去实现了Parcelable 接口,这样就必须重写describeContents()和writeToParcel()这两个方法。其中describeContents()方法直接返回0 就可以了,而writeToParcel()方法中我们需要调用Parcel的writeXxx()方法将Person 类中的字段一一写出。注意字符串型数据就调用writeString()方法,整型数据就调用writeInt()方法,以此类推。

除此之外,我们还必须在Person 类中提供一个名为CREATOR 的常量,这里创建了Parcelable.Creator 接口的一个实现,并将泛型指定为Person。接着需要重写createFromParcel()和newArray()这两个方法,在createFromParcel()方法中我们要去读取刚才写出的name 和age字段,并创建一个Person 对象进行返回,其中name 和age 都是调用Parcel 的readXxx()方法读取到的,注意这里读取的顺序一定要和刚才写出的顺序完全相同。而newArray()方法中的实现就简单多了,只需要new 出一个Person 数组,并使用方法中传入的size 作为数组大小就可以了。

接下来在FirstActivity 中我们仍然可以使用相同的代码来传递Person 对象,只不过在SecondActivity 中获取对象的时候需要稍加改动,如下所示:

Personperson=(Person)getIntent().getParcelableExtra("person_data");

注意这里不再是调用getSerializableExtra()方法,而是调用getParcelableExtra()方法来获取传递过来的对象了,其他的地方都完全相同。这样我们就把使用Intent 来传递对象的两种实现方式都学习完了,对比一下,Serializable的方式较为简单,在这里强调一下,网上很多博客很多文章都说Parcelable要比Serializable效率要高,其实不然,在读取速度方面Serializable其实他要比Parcelable更快,具体我们可以看一下这篇文章

http://www.jianshu.com/p/fcc59fb523b6

五、Intent传递Bitmap

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

Bitmapbitmap=null;Intentintent=newIntent();Bundlebundle=newBundle();bundle.putParcelable("bitmap",bitmap);intent.putExtra("bundle",bundle);

六、定义全局数据,传递数据

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

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

关键部分代码:

第一步自定义Application类:

classMyAppextendsApplication{privateStringmyState;publicStringgetState(){returnmyState;}publicvoidsetState(Strings){myState=s;}}

第二步AndroidManifest.xml中声明:

<applicationandroid:name=".MyApp"android:icon="@drawable/icon"android:label="@string/app_name">

第三步在需要的地方调用:

classBlahextendsActivity{@OverridepublicvoidonCreate(Bundleb){...MyAppappState=((MyApp)getApplicationContext());Stringstate=appState.getState();...}}

高逼格写法

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

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

classMyAppextendsApplication{privateStringmyState;privatestaticMyAppinstance;publicstaticMyAppgetInstance(){returninstance;}publicStringgetState(){returnmyState;}publicvoidsetState(Strings){myState=s;}@OverridepublicvoidonCreate(){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变量会这样,单例对象以及公共静态变量 也会这样~

七、单例模式传参

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

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

①定义一个单例类:

publicclassXclSingleton{//单例模式实例  privatestaticXclSingletoninstance=null;//synchronized 用于线程安全,防止多线程同时创建实例  publicsynchronizedstaticXclSingletongetInstance(){if(instance==null){instance=newXclSingleton();}returninstance;}finalHashMap<String,Object>mMap;privateXclSingleton(){mMap=newHashMap<String,Object>();}publicvoidput(Stringkey,Objectvalue){mMap.put(key,value);}publicObjectget(Stringkey){returnmMap.get(key);}}

②设置参数:

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容