• Android EventBus 3.0.0 使用总结


    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6039221.html
    本文出自【赵彦军的博客】

    前言

    • 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原理图

    这里写图片描述

    如何添加依赖

    • 在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.POSTINGThreadMode.MAINThreadMode.BACKGROUNDThreadMode.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
    }
    
    

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

    参考资料

    【EventBus 3.0的用法详解】
    【EventBus使用详解】
    【腾讯Bugly干货】老司机教你“飙”EventBus3】

  • 相关阅读:
    js window对象属相和方法相关整理资料
    js中把字符串转换成number格式方法
    oracle中CAST函数使用简介【转】
    Oracle使用SQL语句修改字段类型
    @GeneratorValue与@GenericGenerator注解使用心得
    @Column 注解详情
    Spring中的注入方式 和使用的注解 详解
    maven教程
    wxpyhon 对话框
    wxpython 按钮等事件的触发
  • 原文地址:https://www.cnblogs.com/zhaoyanjun/p/6039221.html
Copyright © 2020-2023  润新知