在Activity間傳遞的數據通常比較簡單,可是有時候實際開發中也會傳一些比較複雜的數據,本節一塊兒來學習更多Activity間數據的傳遞。java
在前面幾節咱們只學習了一些經常使用類型的數據傳遞,主要是如下這些重載方法:android
putExtra(String name, boolean value)數組
putExtra(String name, byte value)微信
putExtra(String name, char value)數據結構
putExtra(String name, short value)架構
putExtra(String name, int value)app
putExtra(String name, long value)ide
putExtra(String name, float value)佈局
putExtra(String name, double value)性能
putExtra(String name, String value)
putExtra(String name, CharSequence value)
putExtras(Intent src)
putExtras(Bundle extras)
putExtra(String name, Bundle value)
getBooleanExtra(String name, boolean defaultValue)
getByteExtra(String name, byte defaultValue)
getCharExtra(String name, char defaultValue)
getShortExtra(String name, short defaultValue)
getIntExtra(String name, int defaultValue)
getLongExtra(String name, long defaultValue)
getFloatExtra(String name, float defaultValue)
getDoubleExtra(String name, double defaultValue)
getStringExtra(String name)
getCharSequenceExtra(String name)
getExtras()
getBundleExtra(String name)
能夠發現主要包括boolean、byte、char、short、int、long、float、double、String、CharSequence幾個,固然也能夠先將數據打包爲Bundle或Intent對象再傳遞。
然而在實際開發中常常會碰見以上經常使用類型的數組或列表的組合型數據,其實也很是簡單。
認真的同窗可能已經發現了,每個基本數據類型都有對應數組數據的重載方法,分別以下:
putExtra(String name, boolean[] value)
putExtra(String name, byte[] value)
putExtra(String name, short[] value)
putExtra(String name, char[] value)
putExtra(String name, int[] value)
putExtra(String name, long[] value)
putExtra(String name, float[] value)
putExtra(String name, double[] value)
putExtra(String name, String[] value)
putExtra(String name, CharSequence[] value)
getBooleanArrayExtra(String name)
getByteArrayExtra(String name)
getShortArrayExtra(String name)
getCharArrayExtra(String name)
getIntArrayExtra(String name)
getLongArrayExtra(String name)
getFloatArrayExtra(String name)
getDoubleArrayExtra(String name)
getStringArrayExtra(String name)
getCharSequenceArrayExtra(String name)
putExtra()方法的參數簡單替換爲數組類型的便可,而後使用數組的專用方法獲取,使用起來也很是簡單。
在傳遞列表型數據的時候稍微有一些不一樣了,Intent還提供瞭如下這幾個重載方法:
putIntegerArrayListExtra(String name, ArrayList<Integer> value)
putStringArrayListExtra(String name, ArrayList<String> value)
putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value)
getIntegerArrayListExtra(String name)
getStringArrayListExtra(String name)
getCharSequenceArrayListExtra(String name)
從以上幾個方法能夠知道,Intent自帶傳遞Integer、String、CharSequence三種類型的列表數據,若是須要傳遞到額數據是這幾種類型,或可以轉換爲這幾種類型,那麼數據的傳遞也變得很順利了。
前面學習的幾個方法使用起來仍是比較簡單的,可是會發現一個問題,以上學習的方法沒法傳輸對象(如圖片)、對象的數組或集合,那就須要用到如下這些方法了。
intent還有如下這些重載方法:
putExtra(String name, Serializable value)
putExtra(String name, Parcelable value)
putExtra(String name, Parcelable[] value)
putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value)
getSerializableExtra(String name)
getParcelableExtra(String name)
getParcelableArrayExtra(String name)
getParcelableArrayListExtra(String name)
可能你已經發現了,這裏提到的Serializable類型和Parcelable類型數據究竟是什麼呢?接下來分別來學習。
Serializable接口是啓用其序列化功能的接口,實現java.io.Serializable 接口的類是可序列化的,沒有實現此接口的類將不能使它們的任一狀態被序列化或逆序列化(若是不懂序列化,建議複習鞏固Java部分的序列化知識模塊)。
Serializable實現序列化的方法也很簡單,將須要序列化的類實現Serializable接口,Serializable接口中沒有任何方法,只需在類中指定serialVersionUID的值,該值能夠任意指定一個值。能夠理解爲一個標記,即代表這個類能夠序列化。
假如須要使用Intent傳遞一個Person對象,就先要將其序列化,以下示例代碼:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; import java.io.Serializable; /** * @建立者 鑫鱻 * @描述 Android零基礎入門到精通系列教程 * 首發微信公衆號分享達人秀(ShareExpert) */ public class Person implements Serializable { private static final long serialVersionUID = 1L; // 序列化ID private String name; // 姓名 private int age; // 年齡 public Person() { this.name = "未知"; this.age = 18; } public Person(String name, int age) { this.name = name; this.age = 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; } }
而後便可調用前面的put和get方法來傳遞複雜對象數據了。
因爲Serializable在序列化的時候會產生大量的臨時變量,從而引發頻繁的GC,會影響持續性能。在使用內存的時候,Parcelable比Serializable性能高,因此推薦使用Parcelable。
實現Parcelable接口稍微複雜一些,但效率更高,推薦用這種方法提升性能。實現步驟以下:
將須要序列化的類實現Parcelable接口。
重寫writeToParcel方法,將對象序列化爲一個Parcel對象。
重寫describeContents方法,描述內容接口,默認返回0。實例化靜態內部對象CREATOR實現接口Parcelable.Creator。其中public static final一個都不能少,內部對象CREATOR的名稱也不能改變,必須所有大寫。需重寫本接口中的兩個方法:
createFromParcel(Parcel in) 實現從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層。
newArray(int size) 建立一個類型爲T,長度爲size的數組,僅一句話便可(return new T[size]),供外部類反序列化本類數組使用。
接下來將上面的Person類進行改造,代碼以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; import android.os.Parcel; import android.os.Parcelable; /** * @建立者 鑫鱻 * @描述 Android零基礎入門到精通系列教程 * 首發微信公衆號分享達人秀(ShareExpert) */ public class Person implements Parcelable { private String name; // 姓名 private int age; // 年 protected Person(Parcel in) { // 在讀取Parcel容器裏的數據時,必須按成員變量聲明的順序讀取數據,否則會出現獲取數據出錯 name = in.readString(); age = in.readInt(); } public static final Creator<Person> CREATOR = new Creator<Person>() { // 再經過createFromParcel將Parcel對象映射成原對象 @Override public Person createFromParcel(Parcel in) { return new Person(in); } // 供外部類反序列化本類數組使用 @Override public Person[] newArray(int size) { return new Person[size]; } }; // 內容接口描述,默認返回0便可 @Override public int describeContents() { return 0; } // 按照聲明順序打包數據到Parcel對象中,既將數據打包到Parcel容器中 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } public Person() { this.name = "未知"; this.age = 18; } public Person(String name, int age) { this.name = name; this.age = 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; } }
而後便可調用前面的put和get方法來傳遞複雜對象數據了,固然也能夠是對象的數組或列表型數據。
在使用中須要注意的是,Parcelable不能使用在要將數據存儲在磁盤上的狀況,由於Parcelable不能很好的保證數據的持續性在外界有變化的狀況下。儘管Serializable效率低點,但此時仍是建議使用Serializable。
若是須要將一個對象在多個Activity之間傳遞,或者要連續傳遞好幾層,這種狀況下若是使用以上方法就須要重複屢次,使用起來就特別彆扭,這種狀況就能夠考慮使用全局Application。
Android系統在每一個程序運行的時候都會建立一個Application對象,並且只會建立一個,因此Application 是單例(singleton)模式的一個類,並且Application對象的生命週期是整個程序中最長的,他的生命週期等於這個程序的生命週期。若是想存儲一些值,使用 Application就須要自定義類實現Application類,而後在AndroidManifest.xml中使用咱們自定義的Application 而非系統默認的。
這裏簡單使用一個示例來學習,這裏簡化爲全局保存一個狀態值,能夠方便在各Activity中進行傳遞。首先自定義Application類,代碼以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate; import android.app.Application; /** * @建立者 鑫鱻 * @描述 Android零基礎入門到精通系列教程 * 首發微信公衆號分享達人秀(ShareExpert) */ public class MyApplication extends Application { private int state; public int getState() { return state; } public void setState(int state) { this.state = state; } }
而後在AndroidManifest.xml中聲明,爲application標籤添加android:name屬性,代碼以下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jinyu.cqkxzsxy.android.activity.equipmentupdate"> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
最後在須要使用定義的全局變量的地方便可調用,核心代碼以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class TestActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shop); // ... MyApplication app = (MyApplication) getApplicationContext(); // 保存數據 app.setState(1); // ... // 讀取數據 int state = app.getState(); // ... } }
這樣就很是方便的在各Activity之間進行數據傳遞了。若是想要在整個應用程序中任何位置都能使用,能夠對MyApplication類進行適當的改造,這裏不作過多說明。
可是須要注意的是,當因爲某些緣由(好比系統內存不足),咱們的app會被系統強制殺死,此時再次點擊進入應用時,系統會直接進入被殺死前的那個界面,製造一種歷來沒有被殺死的假象。那麼問題來了,系統強制中止了應用,進程死了,那麼再次啓動時Application天然新的,那裏邊的數據天然木有啦,若是直接使用極可能報空指針或者其餘錯誤。
因此在使用時必定要作好非空判斷,若是數據爲空能夠考慮邏輯上讓應用直接返回到最初的Activity。
上面的Application就是基於單例的,單例模式的特色就是能夠保證系統中一個類有且只有一個實例。
這裏作一個簡單的示例,如定義一個數據持有者類,代碼以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; /** * @建立者 鑫鱻 * @描述 Android零基礎入門到精通系列教程 * 首發微信公衆號分享達人秀(ShareExpert) */ public class DataHolder { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; } private static final DataHolder holder = new DataHolder(); public static DataHolder getInstance() { return holder; } }
而後在使用的地方便可直接調用,以下所示:
// 更新數據
DataHolder.getInstance().setData(data);
// 獲取數據
Stringdata=DataHolder.getInstance().getData();
這樣使用起來也很是簡單。
這個能夠直接在Activity中完成單獨一個數據結構,和單例差很少。
這裏將上面的單例模式類簡單修改,代碼以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; /** * @建立者 鑫鱻 * @描述 Android零基礎入門到精通系列教程 * 首發微信公衆號分享達人秀(ShareExpert) */ public class DataHolder { private static String data; public static String getData() { return data; } public static void setData(String strData) { data = strData; } }
這樣就能夠在啓動Activity以前設置數據,新的Activity中獲取數據。
// 更新數據
DataHolder.setData(data);
// 獲取數據
Stringdata=DataHolder.getData();
須要注意的是,若是數據很大不少(如bitmap),處理不當是很容易致使內存泄露或者內存溢出的,能夠考慮使用WeakReferences 將數據包裝起來。
除了以上介紹的幾種方式,還可使用持久化數據等方法,這裏先不作過多介紹,在後續的學習中會陸續接觸到。
今天就先到這裏,若是有問題歡迎留言一塊兒探討,也歡迎加入Android零基礎入門技術討論微信羣,共同成長!
若是該系列分享對你有幫助,就動動手指關注、點贊、留言吧,你的互動就是對我最大的鼓勵!
此文章版權爲微信公衆號分享達人秀(ShareExpert)——鑫鱻全部,若需轉載請聯繫做者受權,特此聲明!
往期總結回顧:
Android零基礎入門第1節:Android的前世此生
Android零基礎入門第2節:Android 系統架構和應用組件那些事
Android零基礎入門第3節:帶你一塊兒來聊一聊Android開發環境
Android零基礎入門第4節:正確安裝和配置JDK, 高富帥養成第一招
Android零基礎入門第5節:善用ADT Bundle, 輕鬆邂逅女神
Android零基礎入門第6節:配置優化SDK Manager, 正式約會女神
Android零基礎入門第7節:搞定Android模擬器,開啓甜蜜之旅
Android零基礎入門第8節:HelloWorld,個人第一趟旅程出發點
Android零基礎入門第9節:Android應用實戰,不懂代碼也能夠開發
Android零基礎入門第10節:開發IDE大升級,終於迎來了Android Studio
Android零基礎入門第11節:簡單幾步帶你飛,運行Android Studio工程
Android零基礎入門第12節:熟悉Android Studio界面,開始裝逼賣萌
Android零基礎入門第13節:Android Studio個性化配置,打造開發利器
Android零基礎入門第14節:使用高速Genymotion,跨入火箭時代
Android零基礎入門第15節:掌握Android Studio項目結構,揚帆起航
Android零基礎入門第16節:Android用戶界面開發概述
Android零基礎入門第17節:文本框TextView
Android零基礎入門第18節:輸入框EditText
Android零基礎入門第19節:按鈕Button
Android零基礎入門第20節:複選框CheckBox和單選按鈕RadioButton
Android零基礎入門第21節:開關組件ToggleButton和Switch
Android零基礎入門第22節:圖像視圖ImageView
Android零基礎入門第23節:圖像按鈕ImageButton和縮放按鈕ZoomButton
Android零基礎入門第24節:自定義View簡單使用,打造屬於你的控件
Android零基礎入門第25節:簡單且最經常使用的LinearLayout線性佈局
Android零基礎入門第26節:兩種對齊方式,layout_gravity和gravity大不一樣
Android零基礎入門第27節:正確使用padding和margin
Android零基礎入門第28節:輕鬆掌握RelativeLayout相對佈局
Android零基礎入門第29節:善用TableLayout表格佈局
Android零基礎入門第30節:兩分鐘掌握FrameLayout幀佈局
Android零基礎入門第31節:少用的AbsoluteLayout絕對佈局
Android零基礎入門第32節:新推出的GridLayout網格佈局
Android零基礎入門第33節:Android事件處理概述
Android零基礎入門第34節:Android中基於監聽的事件處理
Android零基礎入門第35節:Android中基於回調的事件處理
Android零基礎入門第36節:Android系統事件的處理
Android零基礎入門第37節:初識ListView
Android零基礎入門第38節:初識Adapter
Android零基礎入門第39節:ListActivity和自定義列表項
Android零基礎入門第40節:自定義ArrayAdapter
Android零基礎入門第41節:使用SimpleAdapter
Android零基礎入門第42節:自定義BaseAdapter
Android零基礎入門第43節:ListView優化和列表首尾使用
Android零基礎入門第44節:ListView數據動態更新
Android零基礎入門第45節:網格視圖GridView
Android零基礎入門第46節:列表選項框Spinner
Android零基礎入門第47節:自動完成文本框AutoCompleteTextView
Android零基礎入門第48節:可摺疊列表ExpandableListView
Android零基礎入門第49節:AdapterViewFlipper圖片輪播
Android零基礎入門第50節:StackView卡片堆疊
Android零基礎入門第51節:進度條ProgressBar
Android零基礎入門第52節:自定義ProgressBar炫酷進度條
Android零基礎入門第53節:拖動條SeekBar和星級評分條RatingBar
Android零基礎入門第54節:視圖切換組件ViewSwitcher
Android零基礎入門第55節:ImageSwitcher和TextSwitcher
Android零基礎入門第56節:翻轉視圖ViewFlipper
Android零基礎入門第57節:DatePicker和TimePicker選擇器
Android零基礎入門第58節:數值選擇器NumberPicker
Android零基礎入門第59節:經常使用三大Clock時鐘組件
Android零基礎入門第60節:日曆視圖CalendarView和定時器Chronometer
Android零基礎入門第61節:滾動視圖ScrollView
Android零基礎入門第62節:搜索框組件SearchView
Android零基礎入門第63節:值得借鑑學習的選項卡TabHost
Android零基礎入門第64節:揭開RecyclerView廬山真面目
Android零基礎入門第65節:RecyclerView分割線開發技巧
Android零基礎入門第66節:RecyclerView點擊事件處理
Android零基礎入門第67節:RecyclerView數據動態更新
Android零基礎入門第68節:RecyclerView添加首尾視圖
Android零基礎入門第69節:ViewPager快速實現引導頁
Android零基礎入門第70節:ViewPager打造TabHost效果
Android零基礎入門第71節:CardView簡單實現卡片式佈局
Android零基礎入門第72節:SwipeRefreshLayout下拉刷新
Android零基礎入門第73節:Activity建立和配置
Android零基礎入門第74節:Activity啓動和關閉
Android零基礎入門第75節:Activity狀態和生命週期
Android零基礎入門第76節:Activity數據保存和橫豎屏切換
Android零基礎入門第77節:Activity任務棧和啓動模式
Android零基礎入門第78節:四大組件的紐帶——Intent
Android零基礎入門第79節:Intent 屬性詳解(上)
Android零基礎入門第80節:Intent 屬性詳解(下)
Android零基礎入門第81節:Activity數據傳遞
Android零基礎入門第82節:Activity數據回傳