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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 翁志雄Gson 中级黑马   /  2016-5-10 20:59  /  12543 人查看  /  101 人回复  /   8 人收藏 转载请遵从CC协议 禁止商业使用本文

1. EventBus3.0开发详解 近万开发者收藏

1.1. 什么是EventBus?
eventBusGreenRobot公司出品的一个基于【publish/subscribe】模型的开发库

一.GreenRobot公司除了出品eventBus还出品了比较有名的greenDao(sqlite数据库的orm开发框架)
可以看出GreenDaostar数为4581 EventBusstar数更高 9564 (star数是一个框架/项目影响力的指标)

二.publish/subscribe是一个以发送消息与接收消息模型。以前咱们学习过相似的知识点有

1.sendBroadcastBroadcastReceiver是一个典型
2.handler.sendMessagehandleMessage(Message msg)也是一个典型
3.所以该模型主要包含两个方面 一个是发送消息 一个是接收消息

三.优点
a.代码简洁、层次清晰,大大提高了代码的可读性和可维护性。
b.可以通过简单的代码把数据传递给Activities, Fragments, Threads, Services等等

1.2. 下载EventBus官方SDK
Github下载地址为:

https://github.com/greenrobot/EventBus

1.3. 创建Demo程序
下载到的zip
解压后为


本例使用Android Studio2.0
可以更简单的在 app/build.gradle


如下配置即可

然后运行gradle脚本

1.4. 快速开始
EventBus的方法非常简洁只要掌握以下方法基本就可以完成企业开发了

一.注册与移除
EventBus.getDefault().register(this);注册
EventBus.getDefault().unregister(this);解除
以上两个方法使用上跟广播接收者的注册与使用是类似的有注册必须在使用后移除
Activity为例:
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
    }

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

二.发送消息
发布消息的对象即为【publisher】发布者

EventBus.getDefault().post(new MainMessage("Hello EventBus"));
Post参数类型为普通javaBean

public class MainMessage {
    private String msg;
    public MainMessage(String msg) {
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
}

三.消息的接收处理(建议使用onEventXXX写法)
接收消息的对象即为【subscriber】 订阅者

//主线程中执行
    @Subscribe(threadMode = ThreadMode.MainThread)
    public void onMainEventBus(MainMessage msg) {
        Log.d(TAG, "onEventBus() returned: " + Thread.currentThread());
}
@Subscribe在案例中会细细地讲解 因为是一个大重点

1.5. 案例分析:代替请求码与响应码
MainActivity请求一个NextPageActivity要求该NextPageActivity关闭时把数据传回给MainActivity

startActivityForResult请求代码略

开发步骤

一.在zaowu.itheima.com.eventbusdemo.demo1.FistEvent创建消息类(post作为发送内容)

public class FistEvent {
    private String msg;
    public FistEvent(String msg) {
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

二.zaowu.itheima.com.eventbusdemo.demo1.MainActivity

》》1..加载布局
layout/activity_main.xml

》》2..注册与移除 订阅者

public class MainActivity extends AppCompatActivity {
    private  TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView= (TextView) findViewById(R.id.main_activity_tv);
        //注册事件
        EventBus.getDefault().register(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //移除注册
        EventBus.getDefault().unregister(this);
    }
    public void open(View view) {
        startActivity(new Intent(this, NextPageActivity.class));
    }


》》3..编写订阅者接收消息方法

@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FistEvent event) {
    Log.i("itheima", "onEventMainThread:"+event.getMsg()+Thread.currentThread());
    textView.setText(event.getMsg());
}

l @Subscribe设置订阅者接收处理消息的方法
l 可以给该注解配置线程参数@Subscribe(threadMode = ThreadMode.MAIN)
l ThreadMode用来指定线程

》》4..zaowu.itheima.com.eventbusdemo.demo1.NextPageActivity点击发送消息并关闭

public class NextPageActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next_page);
    }
    public void event1(View view) {
        //发送消息
        FistEvent fistMessage = new FistEvent("NextPageActivity-FistEvent");
        EventBus.getDefault().post(fistMessage);
    }
}


运行前后
==

控件制台显示:消息已经由NextPageActivity传给MainActivity了。显示main主线程

不过首先注意一点eventBus将消息传给参数类型一致的方法

eventBus底层post出消息后,会查找作为subscriber订阅者的参数类型一致的方法然后向这些方法传递post出来的消息。
所以当订阅者有两个以上参数类型一致的方法时都会接收到消息。


建议开发者创建不同的javaBean类来代表不同的消息类型
1.6. ThreadMode原理
ThreadMode.MAIN标注方法运行在主线程,可以更新UI
ThreadMode.BACKGROUND标注方法运行在子线程,,不可以更新UI但可以执行耗时代码
ThreadMode.POSTING 标注方法 运行在跟post一样的线程。如果post在主线程此时相当于MAIN,反之相当于BACKGROUND
ThreadMode.ASYNC标注方法运行在子程。但是跟BACKGROUND有区别。举个例子如果ASYNC标注的方法将要运行时有一个BACKGROUND标注的方法正在运行(延时10),前者标注的方法不会等待10秒结束再运行,而是另外开一个线程运行。

以下是EventBus的源代码分析



1.7. 案例分析:代替广播接收者
如果掌握了EventBus就可以不用广播接收者来发送消息接收消息了,用EventBus更简洁。

一.创建不同的消息对象
zaowu.itheima.com.eventbusdemo.demo2.MainEvent
zaowu.itheima.com.eventbusdemo.demo2.BackGroundEvent
zaowu.itheima.com.eventbusdemo.demo2.AsyncEvent
zaowu.itheima.com.eventbusdemo.demo2.PostingEvent

public class MainEvent {
    private String msg;

    public MainEvent(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}


二.发送不同的消息

layout/activity_threadmode.xml
zaowu.itheima.com.eventbusdemo.demo2.ThreadModeActivity

public void event1(View view) {
    //发送消息
    MainEvent mainEvent = new MainEvent("MainEvent");
    EventBus.getDefault().post(mainEvent);
    Log.i("itheima", "post(mainEvent);"+System.currentTimeMillis());
}
public void event2(View view) {
    //发送消息
    BackGroundEvent backGroundEvent = new BackGroundEvent("BackGroundEvent");
    EventBus.getDefault().post(backGroundEvent);
    Log.i("itheima", "post(backGroundEvent);"+System.currentTimeMillis());
}
public void event3(View view) {
    //发送消息
    AsyncEvent asyncEvent = new AsyncEvent("AsyncEvent");
    EventBus.getDefault().post(asyncEvent);
    Log.i("itheima", "post(asyncEvent);"+System.currentTimeMillis());
}
public void event4(View view) {
    //发送消息
    PostingEvent postingEvent = new PostingEvent("PostingEvent");
    EventBus.getDefault().post(postingEvent);
    Log.i("itheima", "post(postingEvent);"+System.currentTimeMillis());
}


三.接收消息

zaowu.itheima.com.eventbusdemo.demo2.ThreadModeActivity
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMainEvent(MainEvent event) {
    Log.i("itheima", "onMainEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onBackGroundEvent(BackGroundEvent event) {
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Log.i("itheima", "onBackGroundEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onAsyncEvent(AsyncEvent event) {
    Log.i("itheima", "AsyncEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onPostingEvent(PostingEvent event) {
    Log.i("itheima", "onPostingEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis());
}





运行结果【按点击顺序】


1】的运行结果为 ThreadMode.MAIN

2】的运行结果为ThreadMode.BACKGROUND

消息发送到接收到经过了10秒 且运行在子线程
3】的运行结果为ThreadMode.POSTING 与post在一个线程

【4】测试ThreadMode.ASYNC时按以下顺序
运行结果为

说明与ThreadMode.BACKGROUND都是子线程。但是如果后台有BACKGROUND在运行,ASYCN消息不会等待BACKGOUND完成,而是
直接运行。
【源代码下载地址】

游客,如果您要查看本帖隐藏内容请回复


1.8. 总结
有了EeventBus代码会更简洁。同时它比handler,广播,内容观察者的实现都简洁统一还支持消息接收的线程指定。
开发者重点掌握:ThreadMode变量




GIF演示EventBusDemo1.gif (34.51 KB, 下载次数: 51)

GIF演示EventBusDemo1.gif

101 个回复

倒序浏览
近万人收藏的不错哦
回复 使用道具 举报
sinbad88 发表于 2016-5-10 22:25
最近刚好研究这个呢

项目中是否用到了?
回复 使用道具 举报
yanwenyong 发表于 2016-5-11 09:50
不管什么先收藏一下

哈哈 把项目常用到提交过来。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马