Android中EventBus的使用

什么是EventBus

EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法,也可以通过调用普通类开启发送消息。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。

如何使用EventBus

EventBus.png

  1. Publisher是发布者, 通过post()方法将消息事件Event发布到事件总线
  2. EventBus是事件总线, 遍历所有已经注册事件的订阅者们,找到里边的onEvent等4个方法,分发Event
  3. Subscriber是订阅者, 收到事件总线发下来的消息。即onEvent方法被执行。注意参数类型必须和发布者发布的参数一致。

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="?android:attr/dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle"
    android:baselineAligned="false"
    tools:context="com.itheima.eventbusdemo.MainActivity" >
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.itheima.eventbusdemo.LeftFragment"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <fragment
        android:id="@+id/right_fragment"
        android:name="com.itheima.eventbusdemo.RightFragment"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="3" />
</LinearLayout>

fragment_left.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/bt"
        android:textSize="14sp"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮" />
</RelativeLayout>

fragment_right.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/bt"
        android:textSize="14sp"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮" />
</RelativeLayout>

LeftFragment.java

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import de.greenrobot.event.EventBus;
public class LeftFragment extends ListFragment {
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        String[] strs = new String[]{"主线程消息1", "子线程消息1", "主线程消息2","通过普通类发送消息"};
        setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, strs));
    }
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        switch (position) {
            case 0:
                // 主线程
                System.out.println("----------------------主线程发的消息1"
                        + " threadName: "+ Thread.currentThread().getName()
                        + " threadId: " + Thread.currentThread().getId());
                EventBus.getDefault().post(new MsgEvent1("主线程发的消息1"));
                break;
            case 1:
                // 子线程
                new Thread(){
                    public void run() {
                        System.out.println("----------------------子线程发的消息1"
                                + " threadName: "+ Thread.currentThread().getName()
                                + " threadId: " + Thread.currentThread().getId());
                        EventBus.getDefault().post(new MsgEvent1("子线程发的消息1"));
                    };
                }.start();
                break;
            case 2:
                // 主线程
                System.out.println("----------------------主线程发的消息2"
                        + " threadName: "+ Thread.currentThread().getName()
                        + " threadId: " + Thread.currentThread().getId());
                EventBus.getDefault().post(new MsgEvent2("主线程发的消息2"));
                break;
            case 3:
                // 子线程2
                new Thread(){
                    public void run() {
                        System.out.println("----------------------子线程发的类EventBus1消息1"
                                + " threadName: "+ Thread.currentThread().getName()
                                + " threadId: " + Thread.currentThread().getId());
                        new EventBus1();//调用类EventBus1传送消息
                    }
                }.start();
        }
    }
}

RightFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import de.greenrobot.event.EventBus;
public class RightFragment extends Fragment {
    private TextView tv;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 界面创建时,订阅事件, 接受消息
        EventBus.getDefault().register(this);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        // 界面销毁时,取消订阅
        EventBus.getDefault().unregister(this);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_right, null);
        tv = (TextView) view.findViewById(R.id.tv);
        return view;
    }
    /**
     * 与发布者在同一个线程
     * @param msg 事件1
     */
    public void onEvent(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEvent";
        System.out.println("onEvent(MsgEvent1 msg)收到" + content);
    }
    /**
     * 执行在主线程。
     * 非常实用,可以在这里将子线程加载到的数据直接设置到界面中。
     * @param msg 事件1
     */
    public void onEventMainThread(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventMainThread";
        System.out.println("onEventMainThread(MsgEvent1 msg)收到" + content);
        tv.setText(content);
    }
    /**
     * 执行在子线程,如果发布者是子线程则直接执行,如果发布者不是子线程,则创建一个再执行
     * 此处可能会有线程阻塞问题。
     * @param msg 事件1
     */
    public void onEventBackgroundThread(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventBackgroundThread";
        System.out.println("onEventBackgroundThread(MsgEvent1 msg)收到" + content);
    }
    /**
     * 执行在在一个新的子线程
     * 适用于多个线程任务处理, 内部有线程池管理。
     * @param msg 事件1
     */
    public void onEventAsync(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventAsync";
        System.out.println("onEventAsync(MsgEvent1 msg)收到" + content);
    }
    /**
     * 与发布者在同一个线程
     * @param msg 事件2
     */
    public void onEvent(MsgEvent2 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n msg2";
        System.out.println("onEvent(MsgEvent2 msg)收到" + content);
        tv.setText(content);
    }
}

MsgEvent1.java

public class MsgEvent1 {
    private String msg;

    public MsgEvent1(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
}

MsgEvent2.java

public class MsgEvent2 {
    private String msg;

    public MsgEvent2(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
}

EventBus1.java

import de.greenrobot.event.EventBus;
public class EventBus1 {
    public EventBus1() {
        // TODO Auto-generated constructor stub
        EventBus.getDefault().post(new MsgEvent1("类EventBus1发的消息1"));
    }
}
效果图:

效果图.gif

EventBus的ThreadMode

EventBus包含4个ThreadMode:PostThread,MainThread,BackgroundThread,Async
MainThread我们已经不陌生了;我们已经使用过。
具体的用法,极其简单,方法名为:onEventPostThread, onEventMainThread,onEventBackgroundThread,onEventAsync即可
具体什么区别呢?
- onEventMainThread代表这个方法会在UI线程执行
- onEventPostThread代表这个方法会在当前发布事件的线程执行
- BackgroundThread这个方法,如果在非UI线程发布的事件,则直接执行,和发布在同一个线程中。如果在UI线程发布的事件,则加入后台任务队列,使用线程池一个接一个调用。

Async 加入后台任务队列,使用线程池调用,注意没有BackgroundThread中的一个接一个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值