原文地址: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");