1、关于EventBus:

组件通讯在Android开发中是不可避免的,随着业务需求的复杂化,代码中需要我们去处理的业务逻辑难度也不断增大。例如多个Fragment之间的数据传递,Service与Activity、Fragment之间的通讯,BroadCast与Activity、Fragment之间的通讯,各种startActivityForResult的使用,繁杂的操作令我们所厌倦,在GitHub上找了下解决方案,发现了一个不错的开源库EventBus,相信很多做过Android开发的朋友都或多或少对此有所了解。

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

  这是EventBus在GitHub上的开源库地址:https://github.com/greenrobot/EventBus

  EventBus的大体关系是这样的:订阅者(Subscriber)通过订阅事件(Event)到总线,事件发布者(Publisher)发布事件(Event)到总线被订阅者(Subscriber)接收,其实说白了就是软件设计模式里的观察者模式。EventBus在使用的时候就是在合适的地方发布一个事件,使得注册了该事件接收的对象就可以收到通知,进行相应的操作。

2、初探EventBus:

  文绉绉的文字描述令人厌烦,直接上代码说话吧,先来看下要实现的效果:

  

  看似很简单的效果,点击按钮跳转界面,利用Intent发送一个消息,然后TextView接收显示。这是传统上的做法,如果真是这样做,那么写这篇文章的就完全没意义了。其实这里就是利用到了EventBus,并没有用到Intent来传递消息。

  先来看下具体的代码(记得添加EventBus的引用),然后我再分部来解析:

  1. 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
  2. 2
  3. 3 import android.content.Intent;
  4. 4 import android.os.Bundle;
  5. 5 import android.support.v7.app.AppCompatActivity;
  6. 6 import android.view.View;
  7. 7 import android.widget.Button;
  8. 8 import android.widget.TextView;
  9. 9
  10. 10 import de.greenrobot.event.EventBus;
  11. 11
  12. 12 public class MainActivity extends AppCompatActivity {
  13. 13
  14. 14 private Button mBt_1;
  15. 15 private TextView mTv_1;
  16. 16
  17. 17 @Override
  18. 18 protected void onCreate(Bundle savedInstanceState) {
  19. 19 super.onCreate(savedInstanceState);
  20. 20 setContentView(R.layout.activity_main);
  21. 21 //注册绑定EventBus
  22. 22 EventBus.getDefault().register(this);
  23. 23
  24. 24 initView();
  25. 25 initAction();
  26. 26
  27. 27 }
  28. 28
  29. 29 private void initAction() {
  30. 30 mBt_1.setOnClickListener(new View.OnClickListener() {
  31. 31 @Override
  32. 32 public void onClick(View v) {
  33. 33 startActivity(new Intent(MainActivity.this, SecondActivity.class));
  34. 34 }
  35. 35 });
  36. 36 }
  37. 37
  38. 38 private void initView() {
  39. 39 mBt_1 = (Button) findViewById(R.id.bt_1);
  40. 40 mTv_1 = (TextView) findViewById(R.id.tv_info1);
  41. 41 }
  42. 42
  43. 43
  44. 44 //接收所订阅的消息
  45. 45 public void onEventMainThread(MyEvent myEvent) {
  46. 46 if (myEvent.getInfo()!=null) {
  47. 47 mTv_1.setText(myEvent.getInfo());
  48. 48 }
  49. 49
  50. 50 }
  51. 51
  52. 52
  53. 53 @Override
  54. 54 protected void onDestroy() {
  55. 55 super.onDestroy();
  56. 56 //解绑EventBus
  57. 57 EventBus.getDefault().unregister(this);
  58. 58 }
  59. 59 }

MainActivity.java

  1. 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
  2. 2
  3. 3 import android.os.Bundle;
  4. 4 import android.support.v7.app.AppCompatActivity;
  5. 5 import android.view.View;
  6. 6 import android.widget.Button;
  7. 7 import android.widget.Toast;
  8. 8
  9. 9 import de.greenrobot.event.EventBus;
  10. 10
  11. 11 public class SecondActivity extends AppCompatActivity {
  12. 12
  13. 13 private Button mBt_2;
  14. 14
  15. 15 @Override
  16. 16 protected void onCreate(Bundle savedInstanceState) {
  17. 17 super.onCreate(savedInstanceState);
  18. 18 setContentView(R.layout.activity_second);
  19. 19 initView();
  20. 20 initAction();
  21. 21
  22. 22 }
  23. 23
  24. 24 private void initAction() {
  25. 25 mBt_2.setOnClickListener(new View.OnClickListener() {
  26. 26 @Override
  27. 27 public void onClick(View v) {
  28. 28 Toast.makeText(SecondActivity.this,"消息已发送",Toast.LENGTH_SHORT).show();
  29. 29 EventBus.getDefault().post(new MyEvent("我是被发送过来的消息"));
  30. 30
  31. 31 }
  32. 32 });
  33. 33 }
  34. 34
  35. 35 private void initView() {
  36. 36 mBt_2 = (Button) findViewById(R.id.bt_2);
  37. 37 }
  38. 38
  39. 39
  40. 40 }

SecondActivity.java

  1. 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
  2. 2
  3. 3 /**
  4. 4 * Created by Lichenwei
  5. 5 * Date: 2015-10-11
  6. 6 * Time: 18:23
  7. 7 */
  8. 8 public class MyEvent {
  9. 9
  10. 10 private String info;
  11. 11
  12. 12 public MyEvent(String info) {
  13. 13 this.info = info;
  14. 14 }
  15. 15
  16. 16 public String getInfo() {
  17. 17 return info;
  18. 18 }
  19. 19
  20. 20 public void setInfo(String info) {
  21. 21 this.info = info;
  22. 22 }
  23. 23 }

MyEvent

  上面的代码很简单,这里只是抛砖引玉并不做太多复杂的操作,大家可以根据自己的项目需求来添加对应的代码。

3、解析代码:

1、注册EventBus: 

  在添加EventBus的引用后,我们就可以对任意类进行注册绑定和解绑EventBus事件,注册方法和反注册方法很简单,在上面的代码中就可以看出来了,分别是register和unregister,这里的EventBus.getDefault是获取到EventBus实例的意思(单例)。

  1. 1 //注册绑定EventBus
  2. 2 EventBus.getDefault().register(this);
  3. 3 //解绑EventBus
  4. 4 EventBus.getDefault().unregister(this);

2、EventBus事件:

  EventBus很灵活,它对事件不进行任何的限制,也不需要继承或者实现任何类或者接口,可以是任意类型的实体类,好比上面代码提到的MyEvent。

3、EventBus事件发布者:

  有了事件之后,我们就可以对事件进行发布,然后可以被订阅这个事件的所有订阅者所接收。发送事件很简单,有两种方法post与postSticky:

  1. 1 //立即发送事件
  2. 2 EventBus.getDefault().post(Object event);
  3. 3 //延迟发送事件
  4. 4 EventBus.getDefault().postSticky(Objet event);

4、EventBus事件订阅者:

  EventBus的事件订阅者可以是任何已经进行注册EventBus的类,订阅者的数量是没有上限的(很重要,下文会提到),这里的订阅有4种方法,这里都是由onEvent开头的,有着一定的区别:

  1、onEvent:

  如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。   2、onEventMainThread:

  如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。   3、onEventBackground:

  如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。   4、onEventAsync:

  使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync。

  1. 1 public void onEvent(Object event) {}
  2. 2 public void onEventMainThread(Object event) {}
  3. 3 public void onEventBackgroundThread(Object event) {}
  4. 4 public void onEventAsync(Object event) {}

  介绍完EventBus里的所有角色后,我们来理一理订阅/被订阅流程:

  首先,要想成为事件订阅者需要先对EventBus进行注册绑定,然后在本类需要去写一个以onEvent开头的方法来接收处理消息事件,再来我们需要一个自定义的事件可以让事件的发布者发布,让事件的订阅者接收。事件的发布可以通过post方法或者是postSticky方法发布。

4、EventBus所带来的一些方便之处:

  EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。这是我们在文章开头所介绍过的,这里就不多说了,说几个在实际开发中所运用到的地方。

  例如:

  1、当某个页面的某些值发生变化的时候,需要去同时去更改多个页面相对应的值,这时候只要这些类注册订阅了该事件,那么我们就可以很轻松通过post发送消息来进行通讯。

  2、某些时候,我们并不希望发布出来的Event立即被消费掉,而是等到时机成熟。比如说,在一个详情页点赞之后,产生一个事件,这个事件并不立即被消费,而是等用户退出详情页回到商品列表之后,接收到该事件,然后刷新Adapter等。其实这就是之前我们用startActivityForResult和onActivityResult做的事情。这里我们就可以利用postSticky来实现这样的机制。

  总之,EventBus极大的减轻了我们各种组件之间的通讯复杂度,也大大减少了使用ActivityForResult的麻烦。真实值得极力推荐。

5、理解EventBus

  从源码中我们可以知道,当我们在类中注册绑定EventBus的时候,它会去扫描当前类并记录下所有已onEvent开头的方法,存放在一个Map<Key,Value>中,在事件通过post发布之后,EventBus会根据post中实参的类型,去Map中查找对应的方法,并找到了对应的Thread,最终利用Java的反射机制去执行我们的方法。

  onEventMainThread表示这个方法会在UI主线程执行。

  onEventPostThread表示这个方法会在当前发布事件的线程中执行。

  BackgroundThread表示如果在非UI主线程发布的事件,则直接执行,和发布在同一个线程中。如果在UI线程发布的事件,则加入后台任务队列,使用线程池一个接一个调用。

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

http://www.cnblogs.com/lichenwei/p/4873249.html

安卓开发笔记——探索EventBus(转)的更多相关文章

  1. 安卓开发笔记——探索EventBus

    1.关于EventBus: 组件通讯在Android开发中是不可避免的,随着业务需求的复杂化,代码中需要我们去处理的业务逻辑难度也不断增大.例如多个Fragment之间的数据传递,Service与Ac ...

  2. 安卓开发笔记——深入Activity

    在上一篇文章<安卓开发笔记——重识Activity >中,我们了解了Activity生命周期的执行顺序和一些基本的数据保存操作,但如果只知道这些是对于我们的开发需求来说是远远不够的,今天我 ...

  3. 安卓开发笔记——自定义广告轮播Banner(实现无限循环)

    关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...

  4. 安卓开发笔记——丰富多彩的TextView

    随手笔记,记录一些东西~ 记得之前写过一篇文章<安卓开发笔记——个性化TextView(新浪微博)>:http://www.cnblogs.com/lichenwei/p/4411607. ...

  5. 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)

    记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...

  6. 安卓开发笔记——打造万能适配器(Adapter)

    为什么要打造万能适配器? 在安卓开发中,用到ListView和GridView的地方实在是太多了,系统默认给我们提供的适配器(ArrayAdapter,SimpleAdapter)经常不能满足我们的需 ...

  7. 安卓开发笔记——关于Handler的一些总结(上)

    接上篇文章<安卓开发笔记——关于AsyncTask的使用>,今天来讲下在安卓开发里"重中之重"的另一个异步操作类Handler. 今天打算先讲下关于Handler的一些 ...

  8. 安卓开发笔记——Fragment+ViewPager组件(高仿微信界面)

    什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开发复习笔记——ViewPager组件(仿微信引导界面)>,不清楚的朋友可以看看,这里就不再 ...

  9. 安卓开发笔记——Fragment+FragmentTabHost组件(实现新浪微博底部菜单)

    记得之前写过2篇关于底部菜单的实现,由于使用的是过时的TabHost类,虽然一样可以实现我们想要的效果,但作为学习,还是需要来了解下这个新引入类FragmentTabHost 之前2篇文章的链接: 安 ...

随机推荐

  1. Asp.net MVC4之 一个简单的小例子

    练习: 新建一个mvc项目 要求: 有3个视图  Login Index Details 目的:感受一下MVC与传统WebForm的差异性 WebForm的请求模型 MVC请求模型 传统WebForm ...

  2. HTML与XML总结

    阅览<孙欣HTML>和<刘炜XML>过了一段时间,在这里学到的内容用思维导图来概括. HTML与XML都是标记语言. 同样点: HTML文档与XML文档有类似的结构. 前者是( ...

  3. CSS+DIV+HTML(一)--HTML总结

    一.定义 HTML(Hyper Text Markup Language),标记语言. 二.主要内容: HTML元素分为三类:块级标签.内联标签.可变标签.差别在于: 块级元素:在默认情况下会换行显示 ...

  4. zoj 3288 Domination (可能dp)

    ///dp[i][j][k]代表i行j列件,并把一k的概率 ///dp[i][j][k]一种常见的方法有四种传输 ///1:dp[i-1][j][k-1] 可能 (n-(i-1))*j/(n*m-(k ...

  5. svn加入新的文件夹

    方法一: 1.在远程server上生成新的文件夹 svn mkdir http://svn.xxx.com/svn/mobile/strategy/assistant/branches/talk -m ...

  6. ssh否password登陆server

    在线辅导课非常多,但仍录,使用时方便日后查询. 两server,内联网ip每间: 172.16.3.91 (本地计算机) 172.16.3.92 (远程机) 现在想在本地计算机上通过ssh 172.1 ...

  7. js你真的了解offsetWidth吗

    offsetWidth是什么? 答:它可以获取物体宽度的数值 那么就只是这样吗! html部分 <div id="div1"></div> <styl ...

  8. sql二进制数据权限

    (3为权限组合值,结果为1=列表 2=新建 4=修改 8=删除) select 3 & 1 select 3 & 2 select 3 & 4 select 3 & 2 ...

  9. 同一个PC只能运行一个应用实例(考虑多个用户会话情况)

    原文:同一个PC只能运行一个应用实例(考虑多个用户会话情况) class Program { private static Mutex m; [STAThread] static void Main( ...

  10. Orleans:NET的Actor模型

    .NET的Actor模型:Orleans   Orleans是微软推出的类似Scala Akka的Actor模型,Orleans是一个建立在.NET之上的,设计的目标是为了方便程序员开发需要大规模扩展 ...