EventBus使用详解

379 阅读5分钟

以前没有用过EventBus,在技术群里面听别人说EventBus的时候,总感觉高大上,很难使用。但是自己亲自实践一番,才知道使用起来这么简单方便。

所以希望大家,如果对某一项技术比较感兴趣的,不要望而止步,要大胆的尝试去实践,毕竟实践出真理。

大家如果对**EventBus**感兴趣的话,也可以到github了解一下,或者读下这篇文章。

好了,接下来我们开启EventBus之旅吧。

EventBus  .png

这是github上给出来的图解。大家也可以到官网看下

EventBus是一款针对Android优化的发布/订阅事件总线。 主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。 优点是开销小,代码更优雅。以及将发送者和接收者解耦。

从图解中我们看到:发布者将消息提交到EventBus,其中EventBus起到了一个中转的功能,将消息分发给订阅者。

github上介绍使用EventBus只需要三个步骤即可完成。

EventBus使用.png

这里将更加详细的介绍EventBus的使用。

EventBus订阅者有四个方法可以接收到消息:

1、onEvent:使用该函数接收消息,发布消息和接收消息会在同一线程运行,如果发布的在子线程中,那么接收也在子线程中。但不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。

2、onEventMainThread:使用该函数接收消息,发布者无论在那个线程发布消息,onEventMainThread都会在主线程执行。

3、onEventBackground:使用该函数接收消息,发布者无论在那个线程发布消息,onEventBackground函数都会在子线程中执行。

4、onEventAsync:使用该函数接收消息,发布者无论在哪个线程发布消息,都会创建新的子线程在执行onEventAsync。

接下来我们实战一下

github:EventBus
上下载最新jar包,放到你的项目lib下。 或者在你的项目build.gradle加入:compile 'org.greenrobot:eventbus:3.0.0'

接下来就可以使用EventBus了。

创建发布消息的数据集合:

消息.png

public class Teacher {
    public String name;
    public int age;
}
public class Student {
    public String name;
    public int age;
    public int grade;
    public Teacher t;
}

这里我创建两个订阅者,一个发布者

发布订阅者.png

订阅者ReceiverActivity实现:

public class ReceiverActivity extends BaseActivity {

    private static final String TAG = "receiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_receiver);
        //注册订阅
        EventBus.getDefault().register(this);
        this.findViewById(R.id.go_send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ActivityContainer.getInstance().goReceiver02(new ActivityBundle(ReceiverActivity.this));
            }
        });
    }


    @Subscribe
    public void onEventMainThread(Student msg) {
        Log.i(TAG, "ReceiverActivity---------->onEventMainThread");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEventMainThread----Student---->" + name);
            return;
        }
        Log.i(TAG, "onEventMainThread--Student-----null->");
    }

    @Subscribe
    public void onEvent(Student msg) {
        Log.i(TAG, "ReceiverActivity---------->onEvent");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEvent----Student---->" + name);
            return;
        }
        Log.i(TAG, "onEvent--Student-----null->");
    }

    @Subscribe
    public void onEventBackgroundThread(Student msg) {
        Log.i(TAG, "ReceiverActivity---------->onEventBackgroundThread");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEventBackgroundThread----Student---->" + name);
            return;
        }
        Log.i(TAG, "onEventBackgroundThread--Student-----null->");
    }

    @Subscribe
    public void onEventAsync(Student msg) {
        Log.i(TAG, "ReceiverActivity---------->onEventAsync");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEventAsync----Student---->" + name);
            return;
        }
        Log.i(TAG, "onEventAsync--Student-----null->");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解注册订阅
        EventBus.getDefault().unregister(this);
    }
}

使用EventBus.getDefault().register(this);注册订阅者,然后需要实现订阅的方法,这里我把四个订阅方法都实现,实际应用中你可以根据需要实现其中一个就ok了。最后需要在onDestroy方法中解注册,否则会内存泄漏。

下面是ReceiverActivity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.lwj.evenbus.ReceiverActivity">

    <Button
        android:id="@+id/go_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center_horizontal"
        android:text="goSendActivity"/>

</LinearLayout>

订阅者Receiver2Activity实现:


public class Receiver2Activity extends BaseActivity {

    private static final String TAG = "receiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_receiver2);
        EventBus.getDefault().register(this);
        this.findViewById(R.id.go_send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ActivityContainer.getInstance().goSendMsg(new ActivityBundle(Receiver2Activity.this));
            }
        });
    }

    @Subscribe
    public void onEventMainThread(Teacher msg) {
        Log.i(TAG, "Receiver2Activity---------->onEventMainThread");
        if (msg != null) {
            String name = msg.name;
            Toast.makeText(this, msg.name, Toast.LENGTH_SHORT).show();
            Log.i(TAG, "onEventMainThread----Teacher---->" + name);
            return;
        }
        Log.i(TAG, "onEventMainThread--Teacher-----null->");
    }

    @Subscribe
    public void onEvent(Teacher msg) {
        Log.i(TAG, "Receiver2Activity---------->onEvent");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEvent----Teacher---->" + name);
            return;
        }
        Log.i(TAG, "onEvent--Teacher-----null->");
    }

    @Subscribe
    public void onEventBackgroundThread(Teacher msg) {
        Log.i(TAG, "Receiver2Activity---------->onEventBackgroundThread");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEventBackgroundThread----Teacher---->" + name);
            return;
        }
        Log.i(TAG, "onEventBackgroundThread--Teacher-----null->");
    }

    @Subscribe
    public void onEventAsync(Teacher msg) {
        Log.i(TAG, "Receiver2Activity---------->onEventAsync");
        if (msg != null) {
            String name = msg.name;
            Log.i(TAG, "onEventAsync----Teacher---->" + name);
            return;
        }
        Log.i(TAG, "onEventAsync--Teacher-----null->");
    }


    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }
}

实现跟ReceiverActivity一样,只不过这里的订阅方法接收的消息参数不一样。

ReceiverActivity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.lwj.evenbus.Receiver2Activity">

    <Button
        android:id="@+id/go_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center_horizontal"
        android:text="goSendActivity"/>

</LinearLayout>

接下来我们看看SendActivity发布的实现:

public class SendActivity extends BaseActivity {

    private Student mStudent;
    private Teacher mTeacher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_send);

        getData();

        this.findViewById(R.id.send_msg01).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EventBus.getDefault().post(mStudent);
            }
        });
        this.findViewById(R.id.send_msg02).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EventBus.getDefault().post(mTeacher);
            }
        });
        this.findViewById(R.id.send_msg03).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        EventBus.getDefault().post(mStudent);
                    }
                }).start();
            }
        });

    }

    public void getData() {
        mTeacher = new Teacher();
        mTeacher.age = 58;
        mTeacher.name = "光头强";

        mStudent = new Student();
        mStudent.age = 18;
        mStudent.name = "小明";
        mStudent.t = mTeacher;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }


}

发布只需要调用EventBus.getDefault().post(mStudent); 在post方法将发送的消息作为参数就可以了。

SendActivity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.lwj.evenbus.SendActivity">

    <Button
        android:id="@+id/send_msg01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="sendforReceiver01"/>

    <Button
        android:id="@+id/send_msg02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="sendforReceiver02"/>

    <Button
        android:id="@+id/send_msg03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="sendforReceiver03"/>


</LinearLayout>

看看界面

运行结果.png

运行结果:

运行结果.png

此发布者发送的消息,只有订阅了此消息的订阅者才会接收到此消息。这里ReceiverActivity接收了student消息,所以消息只有它接收到。

运行结果.png

Receiver2Activity接收了teacher消息。

运行结果.png

这是在线程中发布的消息,订阅者同样可以接收到消息。

至此,完成了使用eventbus实现发布订阅功能。


欢迎大家关注我的公众号,我会继续努力,分享技术、生活和感悟。

小墨公众号.jpg