1. 程式人生 > >Android activity間通訊幾種方式

Android activity間通訊幾種方式

read flag 進程 destroy ads sage on() sting ogl

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

SerializableParcelable是兩個序列化接口,如果使用BundleIntent之間傳遞對象需要先進行序列化。

  • 序列化的目的

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)

arrayMapHashMap的替代品,因為手機的內存很寶貴,如果內存使用不當很容易引起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!"));

Android activity間通訊幾種方式