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

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!"));

posted @ 2018-09-17 15:38  可爱的黑精灵  阅读(4196)  评论(0编辑  收藏  举报