原文地址:https://www.jianshu.com/p/1169dba99261java
intent传递数据
为何要和intent单独拿出来说,由于Intent传递数据也是很是重要的android
1、简单的传递数据

2、传递数组
bd.putStringArray("StringArray", new String[]{"呵呵","哈哈"}); //可把StringArray换成其余数据类型,好比int,float等等..
读取数组:编程
String[] str = bd.getStringArray("StringArray")
3、传递集合
1)List<基本数据类型或String>
intent.putStringArrayListExtra(name, value) intent.putIntegerArrayListExtra(name, value)
读取集合:json
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>,或更复杂的
解决方法是:外层套个Listapp
//传递复杂些的参数 Map<String, Object> map1 = new HashMap<String, Object>(); map1.put("key1", "value1"); map1.put("key2", "value2"); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); list.add(map1); Intent intent = new Intent(); intent.setClass(MainActivity.this,ComplexActivity.class); Bundle bundle = new Bundle(); //须定义一个list用于在budnle中传递须要传递的ArrayList<Object>,这个是必需要的 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第三方库!ide
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("Java编程思想"); 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序列化对象
可是不知道你有没有发现,putExtra()方法中所支持的数据类型是有限的,虽然经常使用的一些数据类型它都会支持,可是当你想去传递一些自定义对象的时候就会发现无从下手。不用担忧,下面咱们就学习一下使用Intent 来传递对象的技巧。
方式一:Serializable 方式
Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象能够在网络上进行传输,也能够存储到本地。至于序列化的方法也很简单,只须要让一个类去实现Serializable 这个接口就能够了。
好比说有一个Person 类,其中包含了name 和age 这两个字段,想要将它序列化就能够这样写:
public class Person implements Serializable{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
其中get、set 方法都是用于赋值和读取字段数据的,最重要的部分是在第一行。这里让Person 类去实现了Serializable 接口,这样全部的Person 对象就都是可序列化的了。
接下来在FirstActivity 中的写法很是简单:
Person person = new Person(); person.setName("Tom"); person.setAge(20); Intent intent = new Intent(FirstActivity.this, SecondActivity.class); intent.putExtra("person_data", person); startActivity(intent);
能够看到,这里咱们建立了一个Person 的实例,而后就直接将它传入到putExtra()方法中了。因为Person 类实现了Serializable 接口,因此才能够这样写。
接下来在SecondActivity 中获取这个对象也很简单,写法以下:
Person person = (Person) getIntent().getSerializableExtra("person_data");
方式二:Parcelable
除了Serializable 以外,使用Parcelable 也能够实现相同的效果,不过不一样于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent 所支持的数据类型,这样也就实现传递对象的功能了。
下面咱们来看一下Parcelable 的实现方式,修改Person 中的代码,以下所示:
public class Person implements Parcelable { private String name; private int age; @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString(name); dest.writeInt(age); } public static final Parcelable.Creator<Person> CREATOR=new Parcelable.Creator<Person>() { @Override public Person createFromParcel(Parcel source) { // TODO Auto-generated method stub Person person=new Person(); person.name=source.readString(); person.age=source.readInt(); return person; } @Override public Person[] newArray(int size) { // TODO Auto-generated method stub return new Person[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 中获取对象的时候须要稍加改动,以下所示:
Person person = (Person) getIntent().getParcelableExtra("person_data");
注意这里再也不是调用getSerializableExtra()方法,而是调用getParcelableExtra()方法来获取传递过来的对象了,其余的地方都彻底相同。这样咱们就把使用Intent 来传递对象的两种实现方式都学习完了,对比一下,Serializable的方式较为简单,在这里强调一下,网上不少博客不少文章都说Parcelable要比Serializable效率要高,其实否则,在读取速度方面Serializable其实他要比Parcelable更快,具体咱们能够看一下这篇文章
http://www.jianshu.com/p/fcc59fb523b6
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全局对象了!
关键部分代码:
第一步自定义Application类:
class MyApp extends Application { private String myState; public String getState(){ return myState; } public void setState(String s){ myState = s; } }
第二步AndroidManifest.xml中声明:
<application android:name=".MyApp" android:icon="@drawable/icon" android:label="@string/app_name">
第三步在须要的地方调用:
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<String, Object> mMap; private XclSingleton() { mMap = new HashMap<String,Object>(); } 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");