Android EventBus以及观察者模式

2020-10-10  本文已影响0人  文质彬_已然未然

观察者模式简单介绍

观察者模式又被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。这种模式应用广泛,例如在Android中:

            1.Android系统内容提供者 ,内容观察者就采用了这种观察者模式。

            2.RecyClerView和ListView的 Adapter就采用了观察者模式。

            3. 当两个界面想同时观察下载进度的话,可以采用观察者模式来解耦。

**实现步骤**

  1.定义一个观察者接口 interface  Observer,观察者实现观察者接口 ObserverA implements Observer。

    2.定义一个被观察者接口interface Subject,被观察者实现被观察者接口        SubjectDemo implements Subject。

    3.在被观察者发生变化的时候,调用发送通知的方法,回调Observer里面的方法。

示例代码:

**1.被观察者接口**

public interface Subject {

//添加观察者

void addObserver(Observer observer);

//移除指定的观察者

void removeObserver(Observer observer);

//移除所有的观察者

void removeAll();

//通知所有观察者,data 是要通知给观察者的数据,Object是所有类的父类,可以使用多态,当然 你也可以使用 泛型

void notifyAllObserver(Object data);

    //通知某一个观察者

void notify(Observer observer,Object data);

}

**2.观察者接口**

public interface Observer {

// 该方法是通知观察者更新

参数一:subject 是被观察者

参数二:data 是被观察者传递给观察者的 数据

void update(Subject subject,Object data);

}

**3.实现接口,定义具体的被观察者与观察者**

public class SubjectDemo implements Subject {

List<Observer> mList = new ArrayList<>();

  @Override

    public void addObserver(Observer observer) {

        // 确保相同的观察者只含有一个

        if (observer == null) {

            throw new NullPointerException("observer == null");

        }

        if (!mList.contains(observer)) {

            mList.add(observer);

        }

    }

    @Override

    public void removeObserver(Observer observer) {

        mList.remove(observer);

        }

  }

@Override

    public void removeAll() {

        mList.clear();

    }

  @Override

    public void notifyAllObserver(Object data) {

        for (Observer observer : mList) {

            observer.update(this,data);

        }

    }

@Override

    public void notify(Observer observer, Object data) {

        if(observer!=null){

            observer.update(this, data);

        }

    }

}

public class ObserverA implements Observer {

@Override

public void update(Subject subject, Object data) {

System.out.println( data+"我玩甄姬");

}

}

public class ObserverB implements Observer {

@Override

public void update(Subject subject, Object data) {

System.out.println( data+"我玩兰陵王");

}

}

**3.客户端调用**

SubjectDemo subjectDemo = new SubjectDemo();

ObserverA observerA = new ObserverA();

ObserverB observerB = new ObserverB();

subjectDemo.addObserver(observerA);

subjectDemo.addObserver(observerB);

subjectDemo.notifyAllObserver("今晚一起开黑");

观察者优缺点

**优点**

很好地解耦了通知者与观察者,观察者不需要了解通知者内部是怎样实现的,方便于日后代码的修改,体现了 依赖倒转的原则。

**缺点:**

. 抽象通知者(即:被观察者接口Subject)还是依赖了抽象观察者(即:观察者接口Observer),当没有观察者的时候,没办法更新。因为Subject接口里有个添加观察者方法,该方法把Observer接口作为参数传入,否则通知不了观察者更新数据。

. 要求观察者的所有行为要一致。(即:具体的观察者必须实现观察者接口Observer里的所有方法)

**什么是依赖倒转原则**

        简单的说,依赖倒转原则就是要求客户端依赖于抽象耦合,依赖倒转原则的表述是:抽象应当不依赖细节,细节应当依赖于抽象。另一种表述是:要针对接口编程,不要针对实现编程。

        **依赖关系种类:**

1)  零耦合关系:如果两个类之间没有耦合关系,称之为零耦合

2)  具体耦合关系:具体耦合发生在两个具体类(可实例化的)之间,经由一个类对另一个类的直接引用造成。

3)  抽象耦合关系:抽象耦合关系发生在一个具体类和一个抽象类(或者java接口)之间,使两个必须发生关系的类之间存在最大的灵活性。

什么是EventBus

EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent、Handler、BroadCast在Fragment、Activity、Service、线程之间传递消息.优点是开销小,代码更优雅。做到多模块之间低耦合的事件通信,即将发送者和接收者解耦。

EventBus 3.0 之后方法名可以任意指定,不过需要添加 @Subscribe 注解,注解中可以指定线程模型、是否支持粘性事件、优先级。

粘性事件:先发送事件,再注册订阅者,也可以接受到事件。

普通事件:必须要订阅者先注册,然后发送事件,才能被订阅者接收到。

在 Android 下,线程的切换是一个很常用而且很必须的操作,EventBus 除了可以订阅和发送消息之外,它还可以指定接受消息处理消息的线程。

也就是说,无论你 post() 消息时处在什么线程中,EventBus 都可以将消息分发到你指定的线程上去,听上去就感觉非常的方便。

不过无论怎么切换,无外乎几种情况:

• UI 线程切子线程。

• 子线程切 UI 线程。

• 子线程切其他子线程。

在我们使用 EventBus 注册消息的时候,可以通过 @Subscribe 注解来完成注册事件, @Subscribe 中可以通过参数 threadMode 来指定使用那个线程来接收消息。

@Subscribe(threadMode = ThreadMode.MAIN)

fun onEventTest(event:TestEvent){

// 处理事件

}

threadMode 是一个 enum,有多种模式可供选择:

1. POSTING,默认值,那个线程发就是那个线程收。

2. MAIN,切换至主线程接收事件。

3. MAIN_ORDERED,v3.1.1 中新增的属性,也是切换至主线程接收事件,但是和 MAIN 有些许区别,如果事件就是在主线程中发送的,则使用 MAIN 会直接执行。为了让开发和可配置的程度更高,使用MAIN_ORDERED,它不会区分当前线程,而是通通使用 mainThreadPoster 来处理,也就是必然会走一遍 Handler 的消息分发。

4. BACKGROUND,确保在子线程中接收事件。细节就是,如果是主线程发送的消息,会切换到子线程接收,而如果事件本身就是由子线程发出,会直接使用发送事件消息的线程处理消息。

5. ASYNC,确保在子线程中接收事件,但是和 BACKGROUND 的区别在于,它不会区分发送线程是否是子线程,而是每次都在不同的线程中接收事件。

**总之**

1. EventBus 可以通过 threadMode 来配置接收事件的线程。

2. MAIN 和 MAIN_ORDERED 都会在主线程接收事件,区别在于是否区分,发生事件的线程是否是主线程。

3. BACKGROUND 确保在子线程中接收线程,它会通过线程池,使用一个线程循环处理所有的事件。所以事件的执行时机,会受到事件队列前面的事件处理效率的影响(换句话说就是:事件在后台依次进行执行,先发送先执行,后发送后执行)。

4. ASYNC 确保在子线程中接收事件,区别于 BACKGROUND,ASYNC 会每次向线程池中发送任务,通过线程池的调度去执行。但是因为线程池采用的是无界队列(换句话说就是:事件在后台不管先后循序,同时执行),会导致 ASYNC 待处理的事件太多时,会导致 OOM。

 EventBus与观察者模式的关系

EventBus是基于观察者模式的消息处理框架。都是需要订阅时间,发布者发布信息,订阅者及时更新信息。

1.观察者模式的好处是更加的灵活,可以根据自己的需要定制属于自己业务的接口。同时在activity、fragment、service里面没有过多限制,完美解耦。

2.EventBus的好处是不需要再花大把时间去自己封装,提高了开发效率。

今天的分享结束了,再见~

上一篇下一篇

猜你喜欢

热点阅读