美文网首页
EventBus的使用与泛型的封装

EventBus的使用与泛型的封装

作者: Jason_Samuel | 来源:发表于2018-11-27 14:30 被阅读0次

前言

在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是无法解决的,此时需要使用广播等方式来解决。

相关文章

  • EventBus的使用与泛型的封装

    前言 在Android开发中我们经常会碰到Activity、Fragment、Application等对象之间的传...

  • Shawlaw的Android周记 2016年8月7日

    1、使用EventBus进行组件间通信时,要注意EventBus这个消息分发器是无法区分List 这类的泛型对象的...

  • 四 集合 ——第二节 泛型

    文章目录 1、 泛型概念2、 使用泛型的好处3、 泛型的定义与使用 3、1 定义和使用含有泛型的类3、2 含有泛型...

  • Swift 运用协议泛型封装网络层

    Swift 运用协议泛型封装网络层 Swift 运用协议泛型封装网络层

  • 带泛型的BaseDAO封装与使用

    什么是DAO? DAO:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD,而不包...

  • 【已解决】Swift的泛型该如何初始化?

    Swift的泛型该如何初始化? 昨天准备封装一个请求类的时候,对于返回的Model使用了泛型。 但是在泛型初始化的...

  • 泛型的使用

    泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法 泛型类 泛型接口 泛型通配符 泛型方法 静态方法与...

  • 泛型的作用及使用场景

    Android使用泛型的地方很多,比如集成自BaseAdapter实现封装的Adapter,对常用操作进行封装,但...

  • Java-API-集合框架(三)-泛型

    泛型的由来和基本使用 泛型的擦除 泛型类的使用 泛型方法的使用 泛型接口 泛型通配符(?) 通配符? 在api中的...

  • Java 泛型

    java泛型与C#类似,不过必须使用引用类型,不能使用基础类型(int等等),基础类型有相应的封装,比如int,封...

网友评论

      本文标题:EventBus的使用与泛型的封装

      本文链接:https://www.haomeiwen.com/subject/wgtcfqtx.html