EventBus使用入门

转载自:http://bbs.itcast.cn/thread-83609-1-1.html 传智播客
什么是EventBus
EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。
下载EventBus

  1. 下载EventBus库:
    库地址:https://github.com/greenrobot/EventBus/releases
    源码地址:https://github.com/greenrobot/EventBus
  2. 将下载好的EventBus-2.4.0.jar放入libs即可

如何使用EventBus

  1. 定义事件, 定义一个类,继承默认的Object即可,用于区分事件和传输数据。 本例为MsgEvent1和MsgEvent2

  2. 添加订阅者:EventBus.getDefault().register(this); 将所在类作为订阅者,框架会通过反射机制获取所有方法及其参数。
    订阅者所在类可以定义以下一个或多个方法用以接收事件:

    public void onEvent(MsgEvent1 msg)

    public void onEventMainThread(MsgEvent1 msg)

    public void onEventBackgroundThread(MsgEvent1 msg)

    public void onEventAsync(MsgEvent1 msg)

    1
    2
    3
    4
    5
    6
    7

3.发布者发布事件:EventBus.getDefault().post(new MsgEvent1(“主线程发的消息1”));
一旦执行了此方法, 所有订阅者都会执行第二步定义的方法。
4.取消订阅:EventBus.getDefault().unregister(this); 当订阅者不再被使用,或者被关闭时,最好进行取消订阅,不再接受事件消息。
5.注意事项:发布者post方法参数是Object类型,也就是可以发布任何事件。订阅者接受消息时,只要定义的是第二步四个方法任意一个,并且参数和发布者发布的一致,即可被执行。发布者也可以通过第二步接收消息,订阅者也可以作为发布者发消息给自己。

代码实现 (本例是两个Fragment交互, 也可以是Service,Activity,Fragment以及任意类之间交互)
点击左边面板的条目, 可以发送事件,右面板(另一个Fragment)接收到事件,显示界面,打印日志。
代码下载 http://yunpan.cn/cctFTVuWtyIgK 访问密码 66ed
界面如下

1.主界面搭建:

public class MainActivity extends FragmentActivity {

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

}

1
2
3
4
5
6
7
8
9

<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" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

2.定一个事件类MsgEvent1 (MsgEvent2与此一致):

public class MsgEvent1 {
private String msg;

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

}

1
2
3
4
5
6
7
8
9
10
11

3.将右面板作为订阅者, 执行方法并接收数据:

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) {
// 布局只有一个TextView,不再贴代码
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();
            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();
            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();
            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();
            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();
            System.out.println("onEvent(MsgEvent2 msg)收到" + content);
            tv.setText(content);
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

4.在左面板发布消息。(任意类都可以发布消息)

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;
            }
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

分别点击左边条目, Log输出分析
这里写图片描述

源码网盘地址:
http://yunpan.cn/cctFTVuWtyIgK 访问密码 66ed

EventBus框架原理流程图
这里写图片描述

Publisher是发布者, 通过post()方法将消息事件Event发布到事件总线
EventBus是事件总线, 遍历所有已经注册事件的订阅者们,找到里边的onEvent等4个方法,分发Event
Subscriber是订阅者, 收到事件总线发下来的消息。即onEvent方法被执行。注意参数类型必须和发布者发布的参数一致。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值