EventBus使用
在介绍EventBus之前先捋顺以下Android自带的应用内通信方式有哪些?
Android 应用内常用通信方式
1.使用handler进行线程间通信
handler是和Thread绑定的,主线程中创建Hander直接通过new Handler() 来创建即可。自定义线程中则还需要调用Looper.prepare Looper.loop来让Handler起作用,这里就不详细讲解原理及使用了,感兴趣的自己去探索一下。
Handler主要有两个作用,一个是线程间传递消息, 另一个则是post Runnable对象,让Runnable对象在Handler对应的那个线程里运行。
下面用最小代码简单介绍展示一下Handler在线程间传递消息的方式。
示例代码:
新建一个线程,延迟1s后通过主线程的Handler发送消息。
主线程的Handler收到消息后,打印log。
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
|
public
class
MainActivity
extends
Activity{
private
Handler mHandler;
private
Button button;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button1);
mHandler=
new
Handler(){
@Override
public
void
handleMessage(Message msg) {
if
(msg.what==
0xff
){
Log.e(
"what"
,
"I got the Message"
);
}
}
};
button.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
mHandler.sendEmptyMessage(
0xff
);
}
}).start();
}
});
}
}
|
2.使用Interface定义回调,可以用在任意两个对象之间。比如Activity和Fragment通信。
Android官方的Guides也是这么建议的。
参考(http://developer.android.com/guide/components/fragments.html和http://developer.android.com/training/basics/fragments/communicating.html)
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
|
public
static
class
FragmentA
extends
ListFragment {
...
// Container Activity must implement this interface
public
interface
OnArticleSelectedListener {
public
void
onArticleSelected(Uri articleUri);
}
//在Fragment的onAttach方法中,绑定mListener(也就是需要实现了该接口的Activity)
@Override
public
void
onAttach(Activity activity) {
super
.onAttach(activity);
try
{
mListener = (OnArticleSelectedListener) activity;
}
catch
(ClassCastException e) {
throw
new
ClassCastException(activity.toString() +
" must implement OnArticleSelectedListener"
);
}
}
//当Fragment中的Item点击后,回调OnArticleSelectedListener的方法。Activity中实现的方法中即可做相应处理
@Override
public
void
onListItemClick(ListView l, View v,
int
position,
long
id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
}
|
在Activity中需要实现FragmentA中的OnArticleSelectedListener接口
public class MainActivity extends Activity implements FragmentA.OnArticleSelectedListener{
@Override
public void onArticleSelected(Uri articleUri) {
//Do something to response the Item selection
}
}
使用Intent进行组件间的通信
通过Intent来比如启动Service,启动Activity,通过Intent来发送Broadcast,然后注册一个BroadcastReceiver来接收并处理Intent. 这个部分比较基础,就不再赘述了。
EventBus进行应用内通信
如果想深入了解EventBus的实现原理,可以参考 EventBus 源码解析。
简介
EventBus是Android端的一个订阅/发布的消息总线,用在应用程序内,组件之间,线程之间的通信,并且由于事件可以是任意类型的对象,所以使用起来更加的方便快捷。
角色:组件。
Event:就是事件啦。
Subscriber:订阅者,接收特定事件的对象,主要通过onEventXXX()回调接口接收。
Publisher:发布者,post事件,通知订阅者。
其他的先不多介绍了,后面慢慢展开。
使用过程
使用EventBus只有简单的4步
- 1 定义一个Event事件
- 2 注册一个订阅者
- 3 发布一个事件
- 4 接受这个事件
用代码实现这4步就是:
- 1 public class MyEvent()–可以是任意Object。
- 2 EventBus.getDefault().register(this)—比如这时一个Activity,那就等于把Activity注册为一个订阅者。
- 3 EventBus.getDefault().post(event)—随便哪个组件或者线程中发送出一个MyEvent的对象。
- 4 public void onEvent(MyEvent event)–第2步中的Activity中的onEvent方法接收到该事件并处理。注意一定Event类型要对应。如果写成了onEvent(Object event),那就是post什么类型的Event都能接受了。
看起来的确很方便。下面给出一个Activity中的完整代码。也是比较简单,但是能够很清晰的看出EventBus是如何使用的。
示例代码
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
|
public
class
MainActivity
extends
Activity{
private
TextView textView;
private
Button button;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button1);
textView= (TextView) findViewById(R.id.textView1);
//1.注册订阅者
EventBus.getDefault().register(
this
);
button.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
//post事件
EventBus.getDefault().post(
new
MyEvent());
}
});
}
//接收事件的回调
public
void
onEvent(MyEvent event){
Log.e(
"What"
,
"[onEvent]My Thread is "
+Thread.currentThread().getName());
}
|
自定义的事件就是一个空的类,当然也可以加入不同的属性,方法。用来传递信息。
1
2
|
public
class
MyEvent {
}
|
点击按钮后可以看到TextView的内容已更改。
Log
1
|
03
-
29
18
:
56
:
22.738
: E/What(
17402
): [onEvent]My Thread is main</code>
|
onEventXXXX
onEvent函数一共有四种,前面的例子只用到一个onEvent。
函数名 | 含义 | ThreadMode |
---|---|---|
onEvent | 事件处理在事件发送的那个线程执行 | PostThread |
onEventMainThread | 事件在主线程-UI线程执行 | MainThread |
onEventBackgroundThread | 事件在一个后台线程执行(就一个后台线程) | BackgroundThread |
onEventAsync | 事件会单独启动一个线程执行(每个事件都会启动一个线程) | Async |
其中前三个事件处理方式,都应该尽快完成。
onEventMainThread使用演示
onEventMainThread就是会放到主线程去执行的事件处理,一般在其中进行比如UI的更新的操作,比如TextView的更改。下面通过代码展示一下。一个自定义的线程发送该事件,Activity通过onEventMainThread接收到该事件,并更新UI,这个时候就不能使用onEvent了,因为根据上表所示,onEvent会放在发送事件的那个线程中去执行,其实不能进行UI更新操作的。
示例代码
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
|
public
class
MainActivity
extends
Activity{
private
TextView textView;
private
Button button;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button1);
textView= (TextView) findViewById(R.id.textView1);
//1.注册订阅者
EventBus.getDefault().register(
this
);
button.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
EventBus.getDefault().post(
new
MyEvent());
}
}).start();
}
});
}
public
void
onEvent(MyEvent event){
Log.e(
"What"
,
"[onEvent]My Thread is "
+Thread.currentThread().getName());
}
public
void
onEventMainThread(MyEvent event){
Log.e(
"What"
,
"[onEventMainThreadMy] Thread is "
+Thread.currentThread().getName());
textView.setText(
"onEventMainThread called"
);
}
}
|
点击按钮后可以看到TextView的内容已更改。
Log
1
2
|
03
-
29
18
:
54
:
10.728
: E/What(
16993
): [onEvent]My Thread is Thread-
67572
03
-
29
18
:
54
:
10.778
: E/What(
16993
): [onEventMainThreadMy] Thread is main</code>
|
Sticky Event
Sticky Event是指我注册一个sticky的订阅,这样注册之前发送的sticky事件的最近的一个会保存在内存中,错过这个事件的发送的情况下,也可以通过getStickyEvent收到。
postSticky(event) :发送sticky的event 。
registerSticky(subscriber):注册接收sticky事件的订阅者 。
getStickyEvent(Class<Object> eventType):查询最新发布的Event对象。
示例代码
1
2
3
4
5
6
7
8
9
|
public
class
MyEvent {
public
String what;
public
MyEvent(String what) {
super
();
this
.what = what;
}
}
|
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package
com.example.eventbusdemo;
import
de.greenrobot.event.EventBus;
import
android.net.Uri;
import
android.os.Bundle;
import
android.os.Handler;
import
android.os.Message;
import
android.annotation.SuppressLint;
import
android.app.Activity;
import
android.util.Log;
import
android.view.Menu;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.Button;
import
android.widget.TextView;
import
android.widget.Toast;
public
class
MainActivity
extends
Activity {
private
TextView textView;
private
Button sendEvent;
private
Button quaryEvent;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendEvent = (Button) findViewById(R.id.button1);
quaryEvent = (Button) findViewById(R.id.button2);
textView = (TextView) findViewById(R.id.textView1);
// 1.注册订阅者
EventBus.getDefault().registerSticky(
this
);
sendEvent.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// 点击按键发送5个Sticky event
for
(
int
i =
0
; i <
5
; i++) {
EventBus.getDefault().postSticky(
new
MyEvent(String.valueOf(i)));
}
}
});
quaryEvent.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
MyEvent lastEvent = EventBus.getDefault().getStickyEvent(
MyEvent.
class
);
Log.e(
"What"
,
"[quaryEvent] last Event is"
+ lastEvent.what);
}
});
}
public
void
onEvent(MyEvent event) {
Log.e(
"What"
,
"[onEvent] this Event is"
+ event.what);
}
}
|
结果
点击sendEvent按钮:
Log
1
2
3
4
5
6
|
03
-
29
19
:
09
:
40.698
: E/What(
20520
): [onEvent]
this
Event is0
03
-
29
19
:
09
:
40.698
: E/What(
20520
): [onEvent]
this
Event is1
03
-
29
19
:
09
:
40.698
: E/What(
20520
): [onEvent]
this
Event is2
03
-
29
19
:
09
:
40.698
: E/What(
20520
): [onEvent]
this
Event is3
03
-
29
19
:
09
:
40.698
: E/What(
20520
): [onEvent]
this
Event is4
|
点击quaryEvent按钮:
Log
1
2
|
03
-
29
19
:
12
:
31.578
: E/What(
20520
): [quaryEvent] last Event is4
|
技巧
Event类一般都比较小,所以可以把它们都打包在一个Events类中。比如:
1
2
3
4
5
6
|
public
class
Events{
public
static
class
AbcEvent{
}
public
static
class
XyzEvent{
}
}
|