EventBus的使用

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

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.htmlhttp://developer.android.com/training/basics/fragments/communicating.html

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是如何使用的。

示例代码
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());
    }

自定义的事件就是一个空的类,当然也可以加入不同的属性,方法。用来传递信息。

public class MyEvent {
}

点击按钮后可以看到TextView的内容已更改。

Log
03-29 18:56:22.738: E/What(17402): [onEvent]My Thread is main

onEventXXXX

onEvent函数一共有四种,前面的例子只用到一个onEvent。

函数名含义ThreadMode
onEvent事件处理在事件发送的那个线程执行PostThread
onEventMainThread事件在主线程-UI线程执行MainThread
onEventBackgroundThread事件在一个后台线程执行(就一个后台线程)BackgroundThread
onEventAsync事件会单独启动一个线程执行(每个事件都会启动一个线程)Async

其中前三个事件处理方式,都应该尽快完成。

onEventMainThread使用演示

onEventMainThread就是会放到主线程去执行的事件处理,一般在其中进行比如UI的更新的操作,比如TextView的更改。下面通过代码展示一下。一个自定义的线程发送该事件,Activity通过onEventMainThread接收到该事件,并更新UI.这个时候就不能使用onEvent了,因为根据上表所示,onEvent会放在发送事件的那个线程中去执行,其实不能进行UI更新操作的。

示例代码

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

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

Sticky Event

Sticky Event是指我注册一个sticky的订阅,这样注册之前发送的sticky事件的最近的一个会保存在内存中,错过这个事件的发送的情况下,也可以通过getStickyEvent收到。

  • postSticky(event) :发送sticky的event
  • registerSticky(subscriber) :注册接收sticky事件的订阅者
  • getStickyEvent(Class

示例代码

public class MyEvent {
    public String what;

    public MyEvent(String what) {
        super();
        this.what = what;
    }

}
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

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

03-29 19:12:31.578: E/What(20520): [quaryEvent] last Event is4

技巧

Event类一般都比较小,所以可以把它们都打包在一个Events类中。比如:

public class Events{
    public static class AbcEvent{
    }
    public static class XyzEvent{
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值