EventBus的配置&事件的優先級&使用索引

簡介

由前面幾篇我們學習了EventBus的使用、特性等等,這篇我們主要講解的是我們如何在EventBus中如何自定義配置相關事項。還有設置事件的優先級案例分析。

EventBus-Android的發佈 - 訂閱

進入代碼

事例說明

在EventBus的官方文檔中也提到了EventBusBuilder類配置EventBus的各個方面事項。例如:以下是如何構建一個在發佈的事件沒有訂閱者的情況下保持靜態的EventBus:

EventBus eventBus = EventBus.builder()
    .logNoSubscriberMessages(false)
    .sendNoSubscriberEvent(false)
    .build();

另一個例子是當訂閱者拋出異常時失敗:

EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();

配置默認的EventBus實例
使用EventBus.getDefault()是從應用程序中的任何位置獲取共享EventBus實例的簡單方法。EventBusBuilder還允許使用installDefaultEventBus ()方法配置此默認實例 。

例如,可以配置默認的EventBus實例以重新拋出訂閱者方法中發生的異常。但是,僅限於DEBUG構建,因爲這可能會使應用程序在例外情況下崩潰:

EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();

如何使用

優先級

優先級priority使用

接下來我們來學習EventBus的優先級priority表示。priority來表示優先級,數值越大,優先級越高。在同一傳遞線程(ThreadMode)中,較高優先級的訂戶將在優先級較低的其他訂戶之前接收事件。默認優先級爲0。

  • 注:優先級不會影響具有不同ThreadModes的訂閱者的傳遞順序!
@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
   //do something
}

取消事件傳遞

我們知道事件的優先級越高接收的數據最快,所以當優先級不想分發事件給低級別的事件時,可以使用cancelEventDelivery (Object event)這裏的參數是訂閱的實體參數。如下代碼。

  • 注:當優先級更高的想取消事件傳遞時,只有當threadMode = ThreadMode.POSTING處於此狀態才能取消事件傳遞有效。其他不行
@Subscribe(priority = 1000,threadMode = ThreadMode.POSTING)
public void onEvent(MessageEvent event){
     textView.setText(event.message);//設置接收的數據
    //取消事件傳遞,則低級別的事件無法接收到信息,只有在threadMode = ThreadMode.POSTING情況下
    EventBus.getDefault().cancelEventDelivery(event) ;
}

配置索引

訂戶索引是EventBus 3的新功能。它是一種可選的優化,可加快初始訂戶註冊。可以使用EventBus批註處理器在構建期間創建訂戶索引。雖然不需要使用索引,但建議在Android上獲得最佳性能。
當EventBus無法使用索引時,它將在運行時自動回退到反射。因此它仍然可以工作,只是有點慢。所以添加索引可以讓EventBus的使用效率更高。

如何生成索引

使用annotationProcessor

如果您沒有使用Android Gradle Plugin 2.2.0或更高版本,請使用android-apt配置。
要啓用索引生成,您需要使用annotationProcessor 屬性將EventBus批註處理器添加到構建中 。還要設置參數 eventBusIndex以指定要生成的索引的完全限定類。例如,將以下部分添加到app builde.radle構建腳本中:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ] ##這裏要修改爲你項目的包名
            }
        }
    }
}

dependencies {
    implementation 'org.greenrobot:eventbus:3.1.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

如果使用Kotlin,是用kapt

apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied

dependencies {
    implementation 'org.greenrobot:eventbus:3.1.1'
    kapt 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

kapt {
    arguments {
        arg('eventBusIndex', 'com.example.myapp.MyEventBusIndex')
    }
}

如果版本級別比較低則使用,(不推薦,應該升級了Gradle)

buildscript {
    dependencies {
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
    compile 'org.greenrobot:eventbus:3.1.1'
    apt 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

apt {
    arguments {
        eventBusIndex "com.example.myapp.MyEventBusIndex" #這裏要修改爲你項目的包名
    }
}

我的Module:app下build.gladle

apply plugin: 'com.android.application'


android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.eirunye.eventbus"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        javaCompileOptions { # 添加的索引配置
            annotationProcessorOptions {
                arguments = [ eventBusIndex : 'com.eirunye.eventbus.MyEventBusIndex' ]  #這裏要修改爲你項目的包名
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    # 添加的索引配置
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
    implementation 'org.greenrobot:eventbus:3.1.1'
}

配置完成後重新Rebuild Project項目,然後我們到\app\build\generated\source\apt\debug\package\查看是否生成所配置的的文件MyEventBusIndex
MyEventBusIndex.png

package com.eirunye.eventbus;

import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.Map;

/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(PriorityTestActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEvent", com.eirunye.eventbus.bean.MessageEvent.class, ThreadMode.POSTING, 1000,
                    false),
            new SubscriberMethodInfo("onEventLow", com.eirunye.eventbus.bean.MessageEvent.class, ThreadMode.BACKGROUND,
                    1, false),
        }));

        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onMessageEvent", com.eirunye.eventbus.bean.MessageEvent.class),
        }));

        putIndex(new SimpleSubscriberInfo(StickyTestActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onMessageStickyEvent", com.eirunye.eventbus.bean.MessageEvent.class,
                    ThreadMode.MAIN, 0, true),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

如何使用索引

我們可以在Application裏面進行初始化。

EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();

如下代碼:

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
    }
}

如果您想在整個應用中使用默認實例如下

EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();

您可以將相同的原則應用於作爲庫的一部分的代碼(而不是最終的應用程序)。這樣,您可以擁有多個索引類,您可以在EventBus設置期間添加這些索引類如下:

EventBus eventBus = EventBus.builder()
    .addIndex(new MyEventBusAppIndex())
    .addIndex(new MyEventBusLibIndex()).build();

注意:在第一次使用默認EventBus實例之前,這隻能執行一次。對installDefaultEventBus()的後續調用 將引發異常。這可確保您的應用中的行爲一致。所以應該在Application.class使用配置,和使用索引。

代碼混淆

在開發中使用代碼混淆的時候需要加上。

-keepattributes *Annotation*
-keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
 
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

總結

EventBus的Configuration配置和索引使用的時候注意installDefaultEventBus()只能調用一次。否則報錯。
事件的優先級中設置的值越大優先級越高,取消事件傳遞,必須是threadMode = ThreadMode.POSTING在這個情況下纔能有效。
添加自動生成索引時的一些注意事項。

推薦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章