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的數據。arrayMapkey使用二分法排序。在增、刪、改使用的是二分查找法,查找效率比傳統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!"));
