EventBus的使用与泛型的封装

前言

在Android开发中我们经常会碰到Activity、Fragment、Application等对象之间的传递参数问题;然而,它们之间单向通信简单,但遇到多Fragment相互传参通信,或是多Activity之间的异步通信,就需要EventBus出面。

当然,你也可以使用,以下传统的方法:

activity.setArgument(Bundle bundle); // Activity向Fragment发送数据
activity.startActivity(intent); // Activity向Activity发送数据
activity.startActivityForResult(..., ...)
...

EventBus的概念

如同前言所说,EventBus是简化一个APP的内部通信问题,解决多个Activity、Fragment、Application、业务类、工具类等任何Android实体类之间的通信(除了Service)。
EventBus以反射为核心,线程为载体,使用事件“订阅者”与“发送者”的概念,降低模块间的耦合,并且支持多线程。
但由于它是使用的是反射,所以不支持与Service之间通信。

如何使用

使用场景:
两个以上Activity之间信息交互;
群发消息给多个Activity、Fragment、业务类等;
Application实时发送消息给Activity、Fragment、业务类等。

场景不止于此,EventBus适用范围非常广泛。

app/build.gradle中的配置

dependencies {
    compile 'org.greenrobot:eventbus:3.0.0'
}

所以,根据它的“订阅者”与“发送者”的概念,其使用大致分为两步:

第一步、注册“订阅者”

public class TestFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // ...
        EventBus.getDefault().register(this);    // 注册订阅
        // ...
        return inflater.inflate(R.layout.fragment_test, container, false);
    }

    /**
     * 接收订阅消息后,会进入以下代码
     */
    @Subscribe
    public void getMessageByEventBus(String message) {
        // 打印接收到的消息
        Log.d("TAG","-->> Message = " + message);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        EventBus.getDefault().unregister(this);    // 取消订阅
    }
}

以上代码包含三个部分:
1、在onCreateView()中注册订阅
2、使用@Subscribe对一个任意方法标上注解
3、在onDestroyView()中注销订阅
不一定在onCreate里注册,但一定要在“发送”之前进行注册,否则会@Subscribe注解的方法将接收不到消息。
建议在生命周期结束结束时取消订阅。

第二步、发送!

public class TestActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // ...
        // 只需要这句话即可发送
        EventBus.getDefault().post("今天天气不错");
        // ...
    }
}

以上代码EventBus.getDefault().post(""),不仅在Activity中,它还可以写在任何实体类里。
比如下面的这个工具类:

object CityUtil {
    fun getCityName() {
        EventBus.getDefault().post("南京")
    }
}

当执行过post()方法之后,整个进程内,所有被@Subscribe所订阅过的方法,都将收到其发送的信息。例子中我只用post方法传递了String做演示,实际上post(Object)所以可以把任何的对象丢进去进行传递。

泛型的封装

当我们有多个订阅者在同一进程内运行时,每个订阅者难免会接收到不是自己所订阅的消息,所以这时候我们需要使用规范来区分不同订阅者所订阅的消息。

消息实体:

/**
* 这是通配的消息泛型类,不用修改复制进程序里即可
**/
public class MessageEvent<T> {

    private int message;    // 这里的message类似于RequestCode
    private T body;         // 这是需要作为消息的实体

    public MessageEvent(int message, T body) {
        this.message = message;
        this.body = body;
    }

    public int getMessage() {
        return message;
    }

    public T getBody() {
        return body;
    }
}

以上消息实体类中,我们可以把message看做一个requestCode,使订阅者与发送者的message保持一致,这样就可以过滤掉不属于自己订阅的多余消息。

发送者:

public class TestActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // 发送第一条消息
        City myCity = new City();
        myCity.setCityName("南京");
        EventBus.getDefault().post(new MessageEvent<City>(1000, myCity))

        // 发送第二条消息
        Student myStu = new Student();
        myStu.setStudentName("张三");
        EventBus.getDefault().post(new MessageEvent<Student>(2000, myStu))
    }
}

以上发送者,同时发送了两条毫不相干的消息,其中两条消息的message设置的不同,MessageEvent<T>的泛型也设为需要发送的类型。

订阅者:

public class TestFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // ...
        EventBus.getDefault().register(this);    // 注册订阅
        // ...
        return inflater.inflate(R.layout.fragment_test, container, false);
    }

    /**
     * 接收城市实体
     */
    @Subscribe
    public void getCityFromEventBus(final MessageEvent<City> msg) {
        if (msg.getMessage() == 1000) {
            City city = msg.getBody();      // 泛型自动把City转化回来
            Log.d("TAG","-->> City Name = " + city.getCityName());
        }
    }

    /**
     * 接收学生实体
     */
    @Subscribe
    public void getStudentFromEventBus(final MessageEvent<Student> msg) {
        if (msg.getMessage() == 2000) {
            Student stu = msg.getBody();      // 泛型自动把Student转化回来
            Log.d("TAG","-->> Student Name = " + stu .getStudentName());
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        EventBus.getDefault().unregister(this);    // 取消订阅
    }
}

以上的订阅者中,他接收了由发送者同时发来的两个不同的消息,并且分别进行处理打印,Demo中的Student和City两个实体类就在此呈现。

结束语

使用泛型封装过的实体类,可以进一步加强EventBus的适用性,一是简化规范了代码,二是使用时更加方便。但在遇到Service与线程之间通信时EventBus是无法解决的,此时需要使用广播等方式来解决。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,576评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,515评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,017评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,626评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,625评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,255评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,825评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,729评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,271评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,363评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,498评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,183评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,867评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,338评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,458评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,906评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,507评论 2 359

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,283评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,744评论 2 59
  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 6,760评论 6 173
  • 前些天我听着这首歌迷迷糊糊睡着了,被夏天的漩涡带入一片彩色的梦里。因为平时也有用影像和文字记录梦境的习惯,正巧...
    AL09阅读 727评论 0 1
  • 年初定下的目标是60本,截止今天豆瓣上标注读过的是51本,今年有希望读完80本。 回顾一下上半年读过的书,给书友一...
    双宝饭阅读 515评论 1 6