Android activity間通訊幾種方式
Activity 通訊
Bundle
我們可以通過將數據封裝在Bundle
對象中 ,然後在Intent跳轉的時候攜帶Bundle
對象
bundle
本質上是使用arrayMap
實現的
Bundle bundle = new Bundle(); bundle.putString("name", "chenjy"); bundle.putInt("age", 18); Intent intent = new Intent(MainActivity.this, SecondActivity.class); intent.putExtras(bundle); startActivity(intent);
用上述方法可以傳遞基本數據類型和String類型的數據,如果傳遞的是對象就需要進行序列化。
Serializable 和 Parcelable
Serializable
和Parcelable
是兩個序列化接口,如果使用Bundle
在Intent
之間傳遞對象需要先進行序列化。
- 序列化的目的
1.通過序列化操作將對象數據在網絡上進行傳輸(由於網絡傳輸是以字節流的方式對數據進行傳輸的.因此序列化的目的是將對象數據轉換成字節流的形式
2.將對象數據在進程之間進行傳遞(Activity
之間傳遞對象數據時,需要在當前的Activity
中對對象數據進行序列化操作.在另一個Activity
中需要進行反序列化操作講數據取出)
3.Java
平臺允許我們在內存中創建可復用的Java
對象,但一般情況下,只有當JVM
處於運行時,這些對象才可能存在,即,這些對象的生命周期不會比JVM
的生命周期更長(即每個對象都在JVM
中)但在現實應用中,就可能要停止JVM
運行,但有要保存某些指定的對象,並在將來重新讀取被保存的對象。這是Java
對象序列化就能夠實現該功能。(可選擇入數據庫、或文件的形式保存)
4.序列化對象的時候只是針對變量進行序列化,不針對方法進行序列化.
Serializable
Serializable
是由Java
提供的序列化接口,它是一個空接口。
Person
:
public class Person implements Serializable { private String name; private int age; public Person() {} public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public String getName(){ return name; } public int getAge(){ return age; } }
MainActivity
:
Person person = new Person();
person.setName("chenjy");
person.setAge(18);
Bundle bundle = new Bundle();
bundle.putSerializable("person",person);
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtras(bundle);
startActivity(intent);
SecondAcitvity
:
Person person = (Person)getIntent().getSerializableExtra("person");
這種序列化是通過反射機制從而削弱了性能,這種機制也創建了大量的臨時對象從而引起GC頻繁回收調用資源。
Parcelable
Parcelable
是由Android
提供的序列化接口,google
做了大量的優化
Person
:
public class Person implements Parcelable {
private String name;
private int age;
public Person() {}
protected Person(Parcel in) {
name = in.readString();
age = in.readInt();
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
Person person = new Person();
person.name = in.readString();
person.age = in.readInt();
return person;
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
}
運用真實的序列化處理代替反射,大量的引入代碼但是速度會遠快於Serializable
。
所以優先選擇Parcelable
arrayMap 1)
arrayMap
是HashMap
的替代品,因為手機的內存很寶貴,如果內存使用不當很容易引起OOM
.arrayMap
就是通過犧牲時間來換取空間的方式。
arrayMap
使用兩個數組來保存 key 和value的數據。arrayMap
key使用二分法排序。在增、刪、改使用的是二分查找法,查找效率比傳統hashmap
會慢很多。在增、刪元素以後會對空間進行調整,所以不適合數據量較大的場景。
與arrayMap
類似的還有SparseArray
類靜態變量
可以通過public static
定義Activity
的靜態變量然後在其他Activity
使用類名.變量名
傳遞
Application
可以通過在Application
中的全局靜態變量來實現
EventBus
但是當傳輸的數據量較大的時候Parcelable
雖然很便捷,但是會出現異常TransactionTooLargeException
。只時候就需要用到插件EventBus
EventBus
使用的是發布 訂閱者模型,發布者通過EventBus發布事件,訂閱者通過EventBus訂閱事件。當發布者發布事件時,訂閱該事件的訂閱者的事件處理方法將被調用。
- 定義事件
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 訂閱事件
使用@Subscribe
註解來定義訂閱者方法,方法名可以是任意合法的方法名,參數類型為訂閱事件的類型
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
...
}
@Subscribe(threadMode = ThreadMode.MAIN)
中使用了ThreadMode.MAIN這個模式,表示該函數在主線程即UI線程中執行
EventBus總共有四種線程模式,分別是:
ThreadMode.MAIN
:表示無論事件是在哪個線程發布出來的,該事件訂閱方法onEvent都會在UI線程中執行,這個在Android中是非常有用的,因為在Android中只能在UI線程中更新UI,所有在此模式下的方法是不能執行耗時操作的。
ThreadMode.POSTING
:表示事件在哪個線程中發布出來的,事件訂閱函數onEvent就會在這個線程中運行,也就是說發布事件和接收事件在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操作,如果執行耗時操作容易導致事件分發延遲。
ThreadMode.BACKGROUND
:表示如果事件在UI線程中發布出來的,那麽訂閱函數onEvent就會在子線程中運行,如果事件本來就是在子線程中發布出來的,那麽訂閱函數直接在該子線程中執行。
ThreadMode.AYSNC
:使用這個模式的訂閱函數,那麽無論事件在哪個線程發布,都會創建新的子線程來執行訂閱函數。
訂閱者還需要在總線上註冊,並在不需要時在總線上註銷
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 註冊訂閱者
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 註銷訂閱者
EventBus.getDefault().unregister(this);
}
- 發布事件
EventBus.getDefault().post(new MessageEvent("Post Event!"));
Android activity間通訊幾種方式