再读斋

Otto使用详解

Otto是Square推出的基于Guava项目的Android支持库,otto是一个事件总线,用于应用程序的不同组件之间进行有效的通信。OTTO是基于Observer的设计模式。它有发布者,订阅者这两个主要对象。OTTO的最佳实践就是通过反射牺牲了微小的性能,同时极大的降低了程序的耦合度。

Otto官网: http://square.github.io/otto/

目的

Otto框架的主要功能是帮助我们来降低多个组件通信之间的耦合度(解耦)。

应用场景

比如:由界面A跳转至界面B,然后点击B中的Button发送消息更新界面A的视图;
比如:界面有一个界面A,A里面有个Fragment,点击Fragment中的一个Button,跳转至界面B,点击界面B的Button来更新界面A的Fragment视图,等等。

上面列出的两种场景,以前可以用startActivityForResult和interface的方式实现的话会比较麻烦,并且产生了很多的状态判断和逻辑判断,并且可能产生很多不必要的bug,代码量也比较大和繁琐,使用Otto就可以容易的避免这些问题。

基本用法实例

添加Otto

1
2
3
dependencies {
compile 'com.squareup:otto:1.3.8'
}

实现一个Bus的单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 单例Bus对象
* Created by Michael on 2016/4/25.
*/
public final class BusProvider {
public static final Bus bus = new Bus();
public static Bus getInstance() {
return bus;
}
private BusProvider() {
}
}

自定义一个Event事件,封装消息

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 自定义一个Event事件,用来封装信息
* Created by Michael on 2016/4/25.
*/
public class EventFirst {
public String msg;
public EventFirst(String msg) {
this.msg = msg;
}
}

MainActivity,订阅事件

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
public class MainActivity extends AppCompatActivity {
private Button mBtn1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//订阅事件
BusProvider.getInstance().register(this);
mBtn1 = (Button) findViewById(R.id.btn_1);
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,BActivity.class));
}
});
}
/**
* 处理事件EventFirst
* @param event
*/
@Subscribe
public void onEventFirst(EventFirst event) {
mBtn1.setText(event.msg);
System.out.println("onEventFirst:" + event.msg);
}
@Subscribe
public void onEventSecond(EventFirst event) {
mBtn1.setText(event.msg);
System.out.println("onEventFirst:" + event.msg);
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消订阅
BusProvider.getInstance().register(this);
}
}

@Subscrible这个注解在调用了register之后有效,表示订阅一个事件,并且方法用public修饰,方法名可以任意取,参数为自定义的事件类,Otto根据事件对象的类名来判断和处理对应的事件。

BActivity发送订阅事件

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
public class BActivity extends AppCompatActivity {
private Button mBtn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
// BusProvider.getInstance().register(this);
mBtn = (Button) findViewById(R.id.btn_1);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// BusProvider.getInstance().post(new EventFirst("Event First"));
BusProvider.getInstance().post(produceEventFirst());
}
});
}
/**
* 产生事件
* @return
*/
@Produce
public EventFirst produceEventFirst() {
return new EventFirst("Event First");
}
@Override
protected void onDestroy() {
super.onDestroy();
// BusProvider.getInstance().unregister(this);
}
}

@Produce注解告诉Bus该函数是一个事件产生者,产生的事件类型为该函数的返回值。

结果

点击BActivity中的按钮发送消息,然后返回至MainActivity中,打印如下:

1
2
04-25 10:52:13.179 24744-24744/com.example.michael.ottodemo I/System.out: onEventSecond:Event First
04-25 10:52:13.179 24744-24744/com.example.michael.ottodemo I/System.out: onEventFirst:Event First

结果说明:@Subscrible注解的消息处理函数时根据事件对象的类名来确定事件类型,这里的两个方法的参数都是EventFirst类型,所以两个方法都处理了EventFirst事件消息。

总结

通过例子我们可以发现,其实事件发布者不用@Produce注解和注册事件也可以发布消息。但是你要Subscribe订阅事件就一定要register这个类了,否则是接受不到事件的。

刘涤生 wechat