A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 唐杨老师 中级黑马   /  2015-7-23 18:16  /  7956 人查看  /  4 人回复  /   2 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 唐杨老师 于 2015-7-23 18:32 编辑

  • 什么是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)

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

  • 代码实现 (本例是两个Fragment交互, 也可以是Service,Activity,Fragment以及任意类之间交互)
  • 点击左边面板的条目, 可以发送事件,右面板(另一个Fragment)接收到事件,显示界面,打印日志。
  • 代码下载: EventBusDemo.zip (3.41 MB, 下载次数: 449)
  • 界面效果如下file:///C:/Users/poplar/Documents/My%20Knowledge/temp/52b10055-ead4-4dd3-8230-305f1ae54097_128_files/91d11daa-24c9-4e95-ba67-004da250b0fd.jpg



1.主界面搭建:
java
  1. public class MainActivity extends FragmentActivity {

  2.         @Override
  3.         protected void onCreate(Bundle savedInstanceState) {
  4.                 super.onCreate(savedInstanceState);
  5.                 setContentView(R.layout.activity_main);
  6.         }

  7. }
复制代码
xml

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:divider="?android:attr/dividerHorizontal"
  6.     android:orientation="horizontal"
  7.     android:showDividers="middle"
  8.     android:baselineAligned="false"
  9.     tools:context="com.itheima.eventbusdemo.MainActivity" >

  10.     <fragment
  11.         android:id="@+id/left_fragment"
  12.         android:name="com.itheima.eventbusdemo.LeftFragment"
  13.         android:layout_width="0dip"
  14.         android:layout_height="match_parent"
  15.         android:layout_weight="1" />

  16.     <fragment
  17.         android:id="@+id/right_fragment"
  18.         android:name="com.itheima.eventbusdemo.RightFragment"
  19.         android:layout_width="0dip"
  20.         android:layout_height="match_parent"
  21.         android:layout_weight="3" />

  22. </LinearLayout>
复制代码

2. 定一个事件类MsgEvent1 (MsgEvent2与此一致):
  1. public class MsgEvent1 {
  2.         private String msg;
  3.         
  4.         public MsgEvent1(String msg) {
  5.                 super();
  6.                 this.msg = msg;
  7.         }
  8.         public String getMsg() {
  9.                 return msg;
  10.         }
  11. }
复制代码

3. 将右面板作为订阅者, 执行方法并接收数据:
  1. public class RightFragment extends Fragment {
  2.         private TextView tv;
  3.         @Override
  4.         public void onCreate(Bundle savedInstanceState) {
  5.                 super.onCreate(savedInstanceState);               
  6.                 // 界面创建时,订阅事件, 接受消息
  7.                 EventBus.getDefault().register(this);
  8.         }
  9.         @Override
  10.         public void onDestroy() {
  11.                 super.onDestroy();
  12.                 // 界面销毁时,取消订阅
  13.                 EventBus.getDefault().unregister(this);
  14.         }
  15.         @Override
  16.         public View onCreateView(LayoutInflater inflater, ViewGroup container,
  17.                         Bundle savedInstanceState) {
  18.         // 布局只有一个TextView,不再贴代码
  19.                 View view = inflater.inflate(R.layout.fragment_right, null);
  20.                 tv = (TextView) view.findViewById(R.id.tv);
  21.                 return view;
  22.         }
  23.         
  24.         /**
  25.          * 与发布者在同一个线程
  26.          * @param msg 事件1
  27.          */
  28.         public void onEvent(MsgEvent1 msg){
  29.                 String content = msg.getMsg()
  30.                                 + "\n ThreadName: " + Thread.currentThread().getName()
  31.                                 + "\n ThreadId: " + Thread.currentThread().getId();
  32.                 System.out.println("onEvent(MsgEvent1 msg)收到" + content);
  33.         }
  34.         
  35.         /**
  36.          * 执行在主线程。
  37.          * 非常实用,可以在这里将子线程加载到的数据直接设置到界面中。
  38.          * @param msg 事件1
  39.          */
  40.         public void onEventMainThread(MsgEvent1 msg){
  41.                 String content = msg.getMsg()
  42.                                 + "\n ThreadName: " + Thread.currentThread().getName()
  43.                                 + "\n ThreadId: " + Thread.currentThread().getId();
  44.                 System.out.println("onEventMainThread(MsgEvent1 msg)收到" + content);
  45.                 tv.setText(content);
  46.         }
  47.         
  48.         /**
  49.          * 执行在子线程,如果发布者是子线程则直接执行,如果发布者不是子线程,则创建一个再执行
  50.          * 此处可能会有线程阻塞问题。
  51.          * @param msg 事件1
  52.          */
  53.         public void onEventBackgroundThread(MsgEvent1 msg){
  54.                 String content = msg.getMsg()
  55.                                 + "\n ThreadName: " + Thread.currentThread().getName()
  56.                                 + "\n ThreadId: " + Thread.currentThread().getId();
  57.                 System.out.println("onEventBackgroundThread(MsgEvent1 msg)收到" + content);
  58.         }
  59.         
  60.         /**
  61.          * 执行在在一个新的子线程
  62.          * 适用于多个线程任务处理, 内部有线程池管理。
  63.          * @param msg 事件1
  64.          */
  65.         public void onEventAsync(MsgEvent1 msg){
  66.                 String content = msg.getMsg()
  67.                                 + "\n ThreadName: " + Thread.currentThread().getName()
  68.                                 + "\n ThreadId: " + Thread.currentThread().getId();
  69.                 System.out.println("onEventAsync(MsgEvent1 msg)收到" + content);
  70.         }
  71.         
  72.         /**
  73.          * 与发布者在同一个线程
  74.          * @param msg 事件2
  75.          */
  76.         public void onEvent(MsgEvent2 msg){
  77.                 String content = msg.getMsg()
  78.                                 + "\n ThreadName: " + Thread.currentThread().getName()
  79.                                 + "\n ThreadId: " + Thread.currentThread().getId();
  80.                 System.out.println("onEvent(MsgEvent2 msg)收到" + content);
  81.                 tv.setText(content);
  82.         }
  83. }
复制代码

4. 在左面板发布消息。(任意类都可以发布消息)
  1. public class LeftFragment extends ListFragment {

  2.         @Override
  3.         public void onViewCreated(View view, Bundle savedInstanceState) {
  4.                 super.onViewCreated(view, savedInstanceState);

  5.                 String[] strs = new String[]{"主线程消息1", "子线程消息1", "主线程消息2"};
  6.                 setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, strs));
  7.         }
  8.         
  9.         @Override
  10.         public void onListItemClick(ListView l, View v, int position, long id) {
  11.                 switch (position) {
  12.                 case 0:
  13.                         // 主线程
  14.                         System.out.println(
  15.                                 "----------------------主线程发的消息1"
  16.                                 + " threadName: "+ Thread.currentThread().getName()
  17.                                 + " threadId: " + Thread.currentThread().getId());
  18.                         EventBus.getDefault().post(new MsgEvent1("主线程发的消息1"));
  19.                         break;
  20.                 case 1:
  21.                         // 子线程
  22.                         new Thread(){
  23.                                 public void run() {
  24.                                         System.out.println(
  25.                                                 "----------------------子线程发的消息1"
  26.                                                 + " threadName: "+ Thread.currentThread().getName()
  27.                                                 + " threadId: " + Thread.currentThread().getId());
  28.                                         EventBus.getDefault().post(new MsgEvent1("子线程发的消息1"));
  29.                                 };
  30.                         }.start();
  31.                         
  32.                         break;
  33.                 case 2:
  34.                         // 主线程
  35.                         System.out.println(
  36.                                         "----------------------主线程发的消息2"
  37.                                         + " threadName: "+ Thread.currentThread().getName()
  38.                                         + " threadId: " + Thread.currentThread().getId());
  39.                         EventBus.getDefault().post(new MsgEvent2("主线程发的消息2"));
  40.                         break;
  41.                 }
  42.         }
  43.         
  44. }
复制代码



分别点击左边条目, Log输出分析



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

EventBus框架原理流程图



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


4 个回复

倒序浏览
顶顶顶.................................
回复 使用道具 举报
略叼  赞一个
回复 使用道具 举报
赞一个!
回复 使用道具 举报
感谢{:2_30:},学习了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马