概念:
Event:事件(订阅者根据事件来判断是否接收事件)
Subscriber:事件订阅者,接收特定的事件。
Publisher:事件发布者,用于通知Subscriber有事件发生。
其中,Event可以使任意类型对象。Subscriber都是以约定的onEvent开头的函数,具体是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个。Publisher可以通过post(Object)在任意线程任意位置发送事件。
注意:
1.activity和Fragment通过eventbus通信,两个类必须都regist和unregist,unregist最好放到onpause方法中,要不容易出异常。
2.两个类中必须有最少一个接受方法,如果一个也没有也容易出异常。
3.若使用EventBus时出现异常:Subscriber class *** and its super classes have no public methods with the @Subscribe annotation报错的原因:使用EventBus的方法不是public,且缺少@Subscribe这个注解。按照提示改为public,并且加上@Subscribe这个注解就Ok了。如果还解决不了:检查你负责发送消息的Fragment,是不需要regist和unregist。
EventBus 3.0实现Activity和fragment通信、fragment和fragment通信
混淆文件配置:
-keepattributes *Annotation*//keep反射
-keepclassmembers class * { @org.greenrobot.eventbus.Subscribe <methods>;//这个牵涉到你的需求如何,如果你使用了EventBus processor进行加速,你就必须加上这个,只要有这个注解的类和方法都不混淆,为反编译提供了便利。。。如果没有用到加速,这个就不用了}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor//如果你使用了ASYNC 异步线程
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
-keep class de.greenrobot.event.** {*;}
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}
-keepclassmembers class * {@com.xxx.Subscribe ;}
-keepclassmembers class * {@com.xxx.Action ;}
转自https://blog.csdn.net/qq_36621990/article/details/78501307(官方认证的博客)
在这里介绍一下EventBus的用途,EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
可以应用于Activity和fragment之间碎片和碎片之间主线程与子线程之间等场景。
下面我们先了解一下如何利用EventBus在不同线程之间传值。
一,步入正题,首先导入依赖。
compile 'org.greenrobot:eventbus:3.0.0'
二,注册与取消注册
1.在onCreate方法里添加注册代码
EventBus.getDefault().register(this);
2.在onDestroy()方法取消注册
EventBus.getDefault().unregister(this);
三.在需要接受消息的界面添加订阅方法(添加在方法区中)
@Subscribe(threadMode = ThreadMode.MAIN)//MAIN代表主线程
public void receiveMessage(String json){//该方法名可更改,不影响任何东西。
//在主线程中获取子线程发送来的消息设置到TextView中
tv.setText(event.getResult());
}
四.在方法区编写发送消息的方法
public void loadData(final String url){
new Thread(){
@Override
public void run() {
super.run();
String json = 通过url获取网络数据赋值给json
//在子线程当中发送数据给主线程
EventBus.getDefault().post(json);
}
}.start();
}
五.在OnCreate方法中启动发送消息的方法。
loadData(url);
到此为止我们已经可以简单的使用EventBus了。
**
接下来我们来了解一下EventBus如何在不同界面接收特定消息
**
下面我们想一个问题,如果我在其他activity中同样注册EventBus并添加订阅方法会不会一样收到消息呢?答案是可以。
如下:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
EventBus.getDefault().register(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void receiveMessage(String json){
//此处依然可以收到刚才我们所发送的消息
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
那我们如何使不同的界面收到特定的消息呢?
其实很简单
1.我们先创建一个最基础的Java类。例如
public class MessageEvent {
private String recode;
private String result;
private String msg;
public String getRecode() {
return recode;
}
public void setRecode(String recode) {
this.recode = recode;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public MessageEvent() {
}
public MessageEvent(String recode, String result, String msg) {
this.recode = recode;
this.result = result;
this.msg = msg;
}
}
2.然后我们在发送数据时,新建这个类,将要发送的消息赋值给这个类的成员,最后发送这个类对象。如下:
public void loadData(final String url){
new Thread(){
@Override
public void run() {
super.run();
String json = 通过url获取网络数据赋值给json
MessageEvent messageEvent = new MessageEvent("recode",json,"msg");
//在子线程当中发布类给主线程
EventBus.getDefault().post(messageEvent);
}
}.start();
}
3.而在接收消息的时候,我们将订阅方法所接收的类型改成我们发送类的类型。就可以做到只接收此类型的消息。
@Subscribe(threadMode = ThreadMode.MAIN)
public void receiveMessage(MessageEvent event){
tv.setText(event.getResult());
}
到此为止相信大家已经对EventBus有了一定的了解。
**
下面我们如何使用EventBus来完成Activity与Fragment之间、fragment与fragment之间的传值。
**
其实有了上面文章的基础我们利用EventBus来完成各界面之间的传值就非常简单了。
一,肯定是要先导入jar包的。
二,其次我们在想要接收消息的界面完成上述注册和取消注册的步骤并添加订阅方法。
三,可将发送消息的方法添加到任意你想发送消息的地方,比如说某个界面的onCreate中或者某个界面的监听方法中。发送的可以是字符串也可以是某个含有属性的对象。只要对应接收就好。
//发送数据给订阅方法
EventBus.getDefault().post(json);
当我们启动了发送数据的方法,如果相应界面订阅方法所订阅的数据类型与发送数据的数据类型一致就会接收到相应的数据。
其中@Subscribe注解可以有以下几种情况:
@Subscribe(sticky = true)
代表在activity用postSticky信息之后再注册evnetbus,要用这种sticky=true注解方法来接受msg,因为sticky默认为false的
@Subscribe(threadMode = ThreadMode.MAIN)
代表主线程或者子线程post信息的到activity的主线程。
@Subscribe(threadMode = ThreadMode.BACKGROUND)
如果发布线程是主线程,eventbus就会用一个后台子线程发送给主线程,如果发布线程是子线程,那么处理方法就在子线程执行。最后经过或者不经过线程切换都会原来的线程。
@Subscribe(threadMode = ThreadMode.POSTING)
不需要切换线程,发布线程和处理线程一样。简单来说在什么线程post就在什么线程处理。
@Subscribe(threadMode = ThreadMode.ASYNC)
处理方法在主线程和发布线程意外的线程执行,处理一些耗时的操作如网络请求。如果有必要还会开启线程池。
post和postSticky的区别
一般注册后,再post信息要用post,而在没注册前post信息,这时候还没有Subscriber,就要用postSticky。
Aactivity.java
protected void onCreate(Bundle savedInstanceState){
EventBus.getDefault().postSticky("msg from A");
startActivity(new Intent(Aactivity.this,Bactivity.class));
}
Bactivity.java
protected void onCreate(Bundle savedInstanceState){
EventBus.getDefault().register(this);
}
@Subscribe(sticky = true)
public void getMessage(String msg){
Log.i(TAG,msg);//这里打印出 msg from A
}
protected void onDestory(){
EventBus.getDefault.unregister(this);
}
Subscribers的优先级
要在同一中ThreadMode中 ,默认的priority是0,优先级更高的会被先执行。
@Subscribe(priority=1)
public void getMessage(String a){
}
取消订阅者Subscriber
通常由优先级更高的订阅者来取消低优先级的订阅者。
@Subscribe
public void onEvent(String msg){
EventBus.getDefault().cancelEventDelivery(msg);
}
两个Activity传值
1.MainAcivity主方法
public class MainActivity extends AppCompatActivity {
//注解
@ViewInject(R.id.onbut)
private Button but;
private TextView ontv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ontv = (TextView) findViewById(R.id.ontv);
//注册EventBus
EventBus.getDefault().register(this);
}
public void onButton(View v){
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
//特别重要 @Subscribe(threadMode = ThreadMode.MAIN)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventThread(FirstEvent event){
String msg = "onEventThread已经收到了消息"+event.getmEvent();
ontv.setText(msg);
Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
//反注册EventBus
EventBus.getDefault().unregister(this);
}
}
2.SecondeActivity第二个页面
public class SecondActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
}
public void onPlay(View v){
EventBus.getDefault().post(new FirstEvent("FirstEvent btn clicked222"));
}
}
3.FirstEvent的一个方法
public class FirstEvent {
private String mEvent;
public String getmEvent() {
return mEvent;
}
public void setmEvent(String mEvent) {
this.mEvent = mEvent;
}
public FirstEvent(String mEvent){
this.mEvent = mEvent;
}
}