欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android EventBus 3.0.0 使用总结(必看篇)

程序员文章站 2023-12-09 19:35:15
前言 eventbus框架 eventbus是一个通用的叫法,例如google出品的guava,guava是一个庞大的库,eventbus只是它附带的一个小功能,因此实...

前言

eventbus框架

eventbus是一个通用的叫法,例如google出品的guava,guava是一个庞大的库,eventbus只是它附带的一个小功能,因此实际项目中使用并不多。用的最多的是greenrobot/eventbus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解。另一个库square/otto修改自 guava ,用的人也不少。所以今天我们研究的目标是greenrobot的eventbus.

eventbus 简介

1、eventbus3.0.0 是最新的版本。
2、eventbus 是android 发布/订阅事件总线,可简化 activities, fragments, threads, services 等组件间的消息传递。
3、可替代 intent, handler, broadcast ,接口等传统方案,更快,代码更小,50k 左右的 jar 包,代码更优雅,彻底解耦。

github地址:https://github.com/greenrobot/eventbus

eventbus原理图

Android EventBus 3.0.0 使用总结(必看篇)

如何添加依赖

在module的build.gredle 文件中的dependencies标签中添加

compile 'org.greenrobot:eventbus:3.0.0'

例如

apply plugin: 'com.android.application'

android {
  compilesdkversion 24
  buildtoolsversion "24.0.3"

  defaultconfig {
    applicationid "com.eventbus.app"
    minsdkversion 14
    targetsdkversion 24
    versioncode 1
    versionname "1.0"

  }
  buildtypes {
    release {
      minifyenabled false
      proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile filetree(dir: 'libs', include: ['*.jar'])
  compile 'com.android.support:appcompat-v7:24.2.1'

  compile 'org.greenrobot:eventbus:3.0.0'
}

如何使用

注册事件

eventbus.getdefault().register( this );

取消注册

eventbus.getdefault().unregister( this );

发送数据

eventbus.getdefault().post( "我发射了");

简单小例子:使用eventbus传递简单字符串

package com.eventbus.app;

import android.os.bundle;
import android.support.v7.app.appcompatactivity;
import android.view.view;
import android.widget.toast;

import org.greenrobot.eventbus.eventbus;
import org.greenrobot.eventbus.subscribe;
import org.greenrobot.eventbus.threadmode;

public class mainactivity extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    //注册
    eventbus.getdefault().register( this );


    findviewbyid( r.id.button).setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        eventbus.getdefault().post( "我发射了");
      }
    });
  }

  /**
   * 自定义一个方法 hello() ,用来接收事件。
   * 方法名字可以随便写
   * @return
   */

  @subscribe(threadmode = threadmode.main)
  public void hello ( string event){
    /* do something */
    toast.maketext( this , event , toast.length_short).show();
  };


  @override
  protected void ondestroy() {
    super.ondestroy();

    //取消注册 , 防止activity内存泄漏
    eventbus.getdefault().unregister( this );
  }
}

线程模型

在接收事件消息的方法中,可以通过注解的方式设置线程模型,eventbus内置了4中线程模型,分别是threadmode.posting 、threadmode.main、threadmode.background、threadmode.async

比如:

@subscribe(threadmode = threadmode.posting)
  public void onmessageeventpostthread(string event) {
    log.e( "event postthread", "消息: " + event + " thread: " + thread.currentthread().getname() );
  }

  @subscribe(threadmode = threadmode.main)
  public void onmessageeventmainthread(string event) {
    log.e( "event mainthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.background)
  public void onmessageeventbackgroundthread(string event) {
    log.e( "event backgroundthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.async)
  public void onmessageeventasync(string event) {
    log.e( "event async", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

postthread:如果使用事件处理函数指定了线程模型为postthread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为postthread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起anr。

mainthread:如果使用事件处理函数指定了线程模型为mainthread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在ui线程中执行。该方法可以用来更新ui,但是不能处理耗时操作。

backgroundthread:如果使用事件处理函数指定了线程模型为backgroundthread,那么如果事件是在ui线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行ui更新操作。

async:如果使用事件处理函数指定了线程模型为async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行ui更新操作。

小例子1: 在子线程发送数据

package com.eventbus.app;

import android.os.bundle;
import android.support.v7.app.appcompatactivity;
import android.util.log;
import android.view.view;

import org.greenrobot.eventbus.eventbus;
import org.greenrobot.eventbus.subscribe;
import org.greenrobot.eventbus.threadmode;

public class mainactivity extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    //注册
    eventbus.getdefault().register( this );

    findviewbyid( r.id.button).setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        new thread(new runnable() {
          @override
          public void run() {
            log.d( "event 发射数据线程 : " , thread.currentthread().getname() ) ;
            eventbus.getdefault().post( "我发射了");
          }
        }).start() ;
      }
    });
  }


  @subscribe(threadmode = threadmode.posting)
  public void onmessageeventpostthread(string event) {
    log.e( "event postthread", "消息: " + event + " thread: " + thread.currentthread().getname() );
  }

  @subscribe(threadmode = threadmode.main)
  public void onmessageeventmainthread(string event) {
    log.e( "event mainthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.background)
  public void onmessageeventbackgroundthread(string event) {
    log.e( "event backgroundthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.async)
  public void onmessageeventasync(string event) {
    log.e( "event async", "消息: " + event + " thread: " + thread.currentthread().getname());
  }


  @override
  protected void ondestroy() {
    super.ondestroy();

    //取消注册 , 防止activity内存泄漏
    eventbus.getdefault().unregister( this );
  }
}

运行结果:

d/event 发射数据线程 :: thread-109
e/event backgroundthread: 消息: 我发射了 thread: thread-109
e/event postthread: 消息: 我发射了 thread: thread-109
e/event async: 消息: 我发射了 thread: pool-1-thread-2
e/event mainthread: 消息: 我发射了 thread: main

小例子2: 在主线程发送数据

package com.eventbus.app;

import android.os.bundle;
import android.support.v7.app.appcompatactivity;
import android.util.log;
import android.view.view;

import org.greenrobot.eventbus.eventbus;
import org.greenrobot.eventbus.subscribe;
import org.greenrobot.eventbus.threadmode;

public class mainactivity extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    //注册
    eventbus.getdefault().register( this );

    findviewbyid( r.id.button).setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        log.d( "event 发射数据线程 : " , thread.currentthread().getname() ) ;
        eventbus.getdefault().post( "我发射了");
      }
    });
  }

  @subscribe(threadmode = threadmode.posting)
  public void onmessageeventpostthread(string event) {
    log.e( "event postthread", "消息: " + event + " thread: " + thread.currentthread().getname() );
  }

  @subscribe(threadmode = threadmode.main)
  public void onmessageeventmainthread(string event) {
    log.e( "event mainthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.background)
  public void onmessageeventbackgroundthread(string event) {
    log.e( "event backgroundthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @subscribe(threadmode = threadmode.async)
  public void onmessageeventasync(string event) {
    log.e( "event async", "消息: " + event + " thread: " + thread.currentthread().getname());
  }


  @override
  protected void ondestroy() {
    super.ondestroy();

    //取消注册 , 防止activity内存泄漏
    eventbus.getdefault().unregister( this );
  }
}

运行结果:

d/event 发射数据线程 :: main
e/event mainthread: 消息: 我发射了 thread: main
e/event postthread: 消息: 我发射了 thread: main
e/event async: 消息: 我发射了 thread: pool-1-thread-3
e/event backgroundthread: 消息: 我发射了 thread: pool-1-thread-4

黏性事件

除了上面讲的普通事件外,eventbus还支持发送黏性事件。何为黏性事件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。具体用法如下:

注册

eventbus.getdefault().register( this );

事件接收

@subscribe(threadmode = threadmode.main , sticky = true )
public void onmessageeventmainthread(string event) {
log.e( "event mainthread", "消息: " + event + " thread: " + > thread.currentthread().getname());
}

取消注册

eventbus.getdefault().unregister( this ) ;

发送事件

eventbus.getdefault().poststicky( "我发射了");

小例子:在mainactivity发送事件,在activity2里注册并且接收事件

mainactivity源码

package com.eventbus.app;

import android.content.intent;
import android.os.bundle;
import android.support.v7.app.appcompatactivity;
import android.util.log;
import android.view.view;

import org.greenrobot.eventbus.eventbus;

public class mainactivity extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    findviewbyid( r.id.button).setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        log.d( "event 发射数据线程 : " , thread.currentthread().getname() ) ;
        eventbus.getdefault().poststicky( "我发射了");

        startactivity( new intent( mainactivity.this , activity2.class ));
      }
    });
  }
}

activity2源码

package com.eventbus.app;

import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.util.log;

import org.greenrobot.eventbus.eventbus;
import org.greenrobot.eventbus.subscribe;
import org.greenrobot.eventbus.threadmode;

public class activity2 extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_2);
    //注册
    eventbus.getdefault().register( this );
  }

  @subscribe(threadmode = threadmode.main , sticky = true )
  public void onmessageeventmainthread(string event) {
    log.e( "event mainthread", "消息: " + event + " thread: " + thread.currentthread().getname());
  }

  @override
  protected void ondestroy() {
    super.ondestroy();
    //取消注册 , 防止activity内存泄漏
    eventbus.getdefault().unregister( this ) ;
  }
}

这就是粘性事件,能够收到订阅之前发送的消息。但是它只能收到最新的一次消息,比如说在未订阅之前已经发送了多条黏性消息了,然后再订阅只能收到最近的一条消息。

eventbus源码分析

subscribe 接口源码

@documented
@retention(retentionpolicy.runtime)
@target({elementtype.method})
public @interface subscribe {
  threadmode threadmode() default threadmode.posting;

  /**
   * if true, delivers the most recent sticky event (posted with
   * {@link eventbus#poststicky(object)}) to this subscriber (if event available).
   */
  boolean sticky() default false;

  /** subscriber priority to influence the order of event delivery.
   * within the same delivery thread ({@link threadmode}), higher priority subscribers will receive events before
   * others with a lower priority. the default priority is 0. note: the priority does *not* affect the order of
   * delivery among subscribers with different {@link threadmode}s! */
  int priority() default 0;
}

可以看出默认的线程模型是threadmode.posting ;默认黏性事件为false,也就是默认不开启黏性事件;默认的优选级为0 。

eventbus 类部分源码

static volatile eventbus defaultinstance;
 
  /** convenience singleton for apps using a process-wide eventbus instance. */
  public static eventbus getdefault() {
    if (defaultinstance == null) {
      synchronized (eventbus.class) {
        if (defaultinstance == null) {
          defaultinstance = new eventbus();
        }
      }
    }
    return defaultinstance;
  }

getdefault() 是一个单例模式 , 只有一个实例对象。

threadmode 类源码

public enum threadmode {

  /**
   * subscriber will be called in the same thread, which is posting the event. this is the default. event delivery
   * implies the least overhead because it avoids thread switching completely. thus this is the recommended mode for
   * simple tasks that are known to complete is a very short time without requiring the main thread. event handlers
   * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
   */
   
  posting,

  /**
   * subscriber will be called in android's main thread (sometimes referred to as ui thread). if the posting thread is
   * the main thread, event handler methods will be called directly. event handlers using this mode must return
   * quickly to avoid blocking the main thread.
   */
   
  main,

  /**
   * subscriber will be called in a background thread. if posting thread is not the main thread, event handler methods
   * will be called directly in the posting thread. if the posting thread is the main thread, eventbus uses a single
   * background thread, that will deliver all its events sequentially. event handlers using this mode should try to
   * return quickly to avoid blocking the background thread.
   */
   
  background,

  /**
   * event handler methods are called in a separate thread. this is always independent from the posting thread and the
   * main thread. posting events never wait for event handler methods using this mode. event handler methods should
   * use this mode if their execution might take some time, e.g. for network access. avoid triggering a large number
   * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. eventbus
   * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
   */

  async
}

这个类是枚举类,定义了线程模型中的几种类型。

以上这篇android eventbus 3.0.0 使用总结(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。