EventBus3.0的基础使用。

来源:互联网 发布:python正则表达式大全 编辑:程序博客网 时间:2024/05/19 13:06

EventBus是一款针对Android优化的发布/订阅事件总线。

主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。

在我看来,eventbus在各个界面的传值特别方便。无论在哪个界面,只要注册了eventBus都可以收到任何界面post过来的消息,类似于观察者模式,但是比观察者模式实现简单很多,不用写太多的接口。

在需要获取值的地方实现订阅,方法如下:

MainActivity.java

    // 在ui线程执行    @Subscribe(threadMode = ThreadMode.MainThread)    public void onUserEvent(String content) {        tv.setText(content);        Toast.makeText(getApplicationContext(), "MainActivity收到了:"+content, 0).show();    }

在需要传值的地方使用EventBus.getDefault().post();

ThridActivity.java

@Override    public void onClick(View v) {        EventBus.getDefault().post("你好");    }

回到MainActivity
这里写图片描述

执行post方法的时候,MainActivity的onUserEvent收到post传来的值。需要注意的是如果是int这些基础类型,需要写成Integer等封装类
onUserEvent这个方法名,与EventBus没有关系,是根据自己的情况命名。

现在知道eventBus简单传值了,在很多情况下,简单的传值并不能满足需求。

比如intent传自己的封装类:

1:Gson将他转成字符串,传过去再用Gson转回来。

2:实现Serializable接口,或者Parcelable接口。

在EventBus就直接写好订阅,然后在需要传的地方post就行了。

public class Student {    String name;    String age;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAge() {        return age;    }    public void setAge(String age) {        this.age = age;    }    @Override    public String toString() {        return "name =  " + name + ",age = " + age;    }}

MainActivity.java

    @Subscribe(threadMode = ThreadMode.MainThread)    public void onUserEvent(Student student) {        tv.setText(student.toString());    }

Thrid.java

    @Override    public void onClick(View v) {//      EventBus.getDefault().post("你好");        Student s = new Student();        s.setName("Hoyn");        s.setAge("18");        EventBus.getDefault().post(s);    }

回到MainActivity
这里写图片描述

再接着传更复杂的list集合。

MainActivity.java

    @Subscribe(threadMode = ThreadMode.MainThread)    public void onUserEvent(List<Student> list_student) {        String str_student = "";        for (Student student : list_student) {            str_student += student.toString();        }        tv.setText(str_student);    }

ThridActivity.java

    @Override    public void onClick(View v) {//      EventBus.getDefault().post("你好");        List<Student> list_student = new ArrayList<Student>();        Student s = new Student();        s.setName("Hoyn");        s.setAge("18");        list_student.add(s);        list_student.add(s);        list_student.add(s);        EventBus.getDefault().post(list_student);    }

回到MainActivity
这里写图片描述

好了,简单的传值就这样了。

只不过现在都是main->second->thrid。thrid给main传值。类似于startActivityForResult的回调,只不过他不是Activity之间的回调,而是你想回调给栈内任何一个注册了EventBus的Activity或Fragment(Service什么的就不说了)。

那么,main>second的带值传递要怎么做呢?

一般来说是:

Intent intent = new Intent(xxxx);intent.put(xxxx);startActivity(intent);

EventBus:

MainActivity.java

@Override    public void onClick(View v) {        Intent intent = new Intent(MainActivity.this, SecondActivity.class);        Student student = new Student();        student.setAge("18");        student.setName("Hoyn");        EventBus.getDefault().postSticky(student);        startActivity(intent);    }

SecondActivity.java

@Override    public void onClick(View v) {        Intent intent = new Intent(MainActivity.this, SecondActivity.class);        Student student = new Student();        student.setAge("18");        student.setName("Hoyn");        EventBus.getDefault().postSticky(student);        startActivity(intent);    }

SecondActivity:
这里写图片描述

接下来就是,比较复杂的就是传list< T >了。EventBus是根据class反射建立对象的,list只有list的class,没有list< T >的class,又没有gson的用type来建立List集合对象

我说下我的解决方法吧。

MainActivity.java

    List<Student> list  = new ArrayList<Student>();    @Override    public void onClick(View v) {        Intent intent = new Intent(MainActivity.this, SecondActivity.class);        Student student= new Student();        student.setAge("18");        student.setName("Hoyn");        list.add(student);        list.add(student);        EventBus.getDefault().postSticky(student);        startActivity(intent);    }    //在第二个页面post(true)过来,他就执行了这个页面的post(List)    @Subscribe(threadMode = ThreadMode.MainThread)    public void isOK(Boolean isOK) {        if(isOK){            EventBus.getDefault().post(list);        }    }

SecondActivity

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_second);        tv = (TextView) findViewById(R.id.textView);        findViewById(R.id.button).setOnClickListener(this);        EventBus.getDefault().register(this);        EventBus.getDefault().post(true);    }    @Subscribe(threadMode = ThreadMode.MainThread)    public void getStudentList(List<Student> list_student) {        String str_student = "";        for (Student student : list_student) {            str_student += student.toString();        }        tv.setText(str_student);    }

SecondActivity:
这里写图片描述

好了,传值和回调值都解决了。这就是EventBus强大之处。

ps.说一下在使用EventBus3.0遇到的坑。
1、EventBus在post是不需要注册和反注册的,任何界面都能直接EventBus.getDefault().post()
2、在注册和反注册的界面,必须实现至少一个订阅@Subscribe(threadMode = ThreadMode.MainThread)方法,否则提示没有方法,造成崩溃
3、订阅的事件是同时触发的(如果可以单独选择触发请告诉我,谢谢),触发是根据参数,而不是方法名。

在不同的acitivity分别订阅了这两个事件,任何一个地方post(String)两个地方都会触发。@Subscribe(threadMode = ThreadMode.MainThread)public void getSS(String aa);@Subscribe(threadMode = ThreadMode.MainThread)public void getBB(String bb);在同一个activity订阅了2个事件,貌似2个都会触发。(记不清了),总之别这样做,很容易出现问题。

4、List< Student >,List< Teacher >在EventBus是认为同一个集合,他只是反射的list.class,至于里面的泛型T他是不管的,也就是说只要post了任何一个集合,订阅了这两个事件的都会收到这个集合,然后报错。所以一般不推荐写太多的集合,如果一定需要,可能需要自己写一个集合类继承ArrayList,用这种方法区别List(未测试,如果不行,请联系我删除这句)

转一下ThreadMode的四中方式,转载自http://blog.csdn.net/angcyo/article/details/48166849

    @Subscribe(threadMode = ThreadMode.MainThread) //在ui线程执行        public void onUserEvent(UserEvent event) {    }    @Subscribe(threadMode = ThreadMode.BackgroundThread) //在后台线程执行        public void onUserEvent(UserEvent event) {    }    @Subscribe(threadMode = ThreadMode.Async) //强制在后台执行        public void onUserEvent(UserEvent event) {    }    @Subscribe(threadMode = ThreadMode.PostThread) //默认方式, 在发送线程执行        public void onUserEvent(UserEvent event) {    }

附上Demo

0 0