EvenBus的正确使用姿势-index

本文探讨了EventBus在Android开发中的性能提升策略,通过对比使用EventBusIndex前后注册方法的耗时,展示了使用Index的重要性和效率优势。

前言

最近在学习商学院的一些知识,有一些学习心得,在这里分享给大家。我在看一篇博客或者一些书籍的时候,都会按照下面的模式进行学习:

  1. 讲什么(作者需要讲了什么)
  2. 如何讲明白(作者通过什么样的方式讲明白自己的观点)
  3. 如何运用(实际应用场景)
  4. 拓展思考(结合自己的理解,进行发散性思考)

这样在学习的过程中有思考,有总结;更能抓住重点和提升学习效率。

eventBusIndex的性能提升

在没有使用EventBus之前,一般都是使用广播来实现组件之间的通信,但是随着EventBus的普及以及EventBusIndex和APT的结合,已经慢慢的接受了EventBus。3.0之前的版本都是通过反射,遍历类中所有的方法,然后寻找符合条件的方法,这种方式在一个类方法数量少的前提下没有什么问题,但是如果类中的方法较多,存在一定的性能影响。下面结合实际的测试结果来说明使用EventBusIndex和不使用之间的性能差别。

常规使用

EventBus的使用文档参考 官方文档

测试机型::华为 Honor 6X

测试代码一:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        long startTime = System.currentTimeMillis();
        EventBus.getDefault().register(this);
        long endTime = System.currentTimeMillis();
        Log.d("event_bus","cut_time:"+String.valueOf(endTime - startTime));

    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void loginEvent(LoginEvent event){

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void userEvent(UserEvent event){

    }
        @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }
}

测试结果: 7毫秒(EventBus.register()方法执行消耗7毫秒)

测试代码二: 加入 60个方法

    public void test1(){}
    public void test2(){}
    public void test3(){}
    .......
    public void test67(){}
    public void test68(){}
    public void test69(){}

测试结果: 10毫秒(EventBus.register()方法执行消耗10毫秒)
register所执行所消耗时间会随着方法的增多而增多。

使用eventBusIndex

eventBusIndex的使用方法如下:


android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.mytestproject"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        javaCompileOptions {
            annotationProcessorOptions {
                //包名可以随意,但是建议和AndroidManifext.xml中的 package 一致
                //类名也可以随便取
                arguments = [eventBusIndex: 'com.example.mytestproject.TextEventBusIndex']
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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'
    //EventBus
    implementation 'org.greenrobot:eventbus:3.1.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

注意:配置完成需要rebuild,完成可在build目标下看到生成的类。
在这里插入图片描述
在Application中加入全局配置,其他的使用方式不变。

EventBus.builder().addIndex(new TextEventBusIndex()).installDefaultEventBus();

按照第一次的两种方法进行测试,耗时为:2毫秒

由此可以看出不加index是加index耗时的3倍以上,虽然时间基本几毫秒级别,但是对整个比例确很大。使用index后以及结合APT,会在编译期间将相应的类以及对应的方法保存起来,这就比在运行期间通过反射获取符合条件的方法要高效得多。

总结:

  1. 讲了什么:讲了EventBus的index使用以及使用index的重要性
  2. 如何讲明白:通过代码示例index的使用以及对比使用index和不使用index所消耗的时间比例
  3. 拓展思考:随着Android开发者的增多,对技术的要求也越来越高,我们需要在能够优化的地方尽量优化,从而提升性能,提升体验;同时也是提升自我。
<think>我们正在讨论在Vue2中使用EventBus(事件总线)的问题。具体场景是在layout组件中通过$on监听事件,需要确定何时使用$off移除监听。 根据引用[2]的内容,为了避免重复创建监听导致回调函数多次执行,需要在组件销毁前移除监听事件。引用[2]的示例代码是在组件的beforeDestroy生命周期钩子中移除监听。 引用[3]中展示了如何封装一个EventBus,其中包含了$off方法用于取消事件订阅。 因此,在Vue2中,为了避免内存泄漏和重复监听,应该在组件的beforeDestroy(或destroyed)生命周期钩子中使用$off移除事件监听。 具体步骤: 1. 在layout组件中,使用EventBus.$on('事件名', 回调函数)来监听事件。 2. 在layout组件的beforeDestroy生命周期钩子中,使用EventBus.$off('事件名')来移除对该事件的监听。 注意:如果同一个事件监听了多个回调函数,且希望移除所有回调,可以直接使用$off('事件名')。如果希望移除某个特定的回调,则需要传入该回调函数作为第二个参数(但通常我们直接移除整个事件的所有监听)。 示例代码: 在layout组件中: ``` import EventBus from './event-bus.js' export default { created() { // 监听事件 EventBus.$on('some-event', this.handleSomeEvent); }, beforeDestroy() { // 移除事件监听 EventBus.$off('some-event', this.handleSomeEvent); }, methods: { handleSomeEvent(payload) { // 处理事件 } } } ``` 注意:如果使用匿名函数作为回调,则无法单独移除,因此建议使用组件内定义的方法(如上面的handleSomeEvent),这样可以在移除时指定同一个函数。 另外,引用[5]提到了使用mitt库(Vue3中常用,但Vue2也可以使用)来创建事件总线,其移除监听的方式类似。 结论:在Vue2中,在layout组件中监听事件后,应该在组件的beforeDestroy(或destroyed)生命周期钩子中移除监听。 相关问题: 1. 在Vue2中,EventBus使用有哪些注意事项? 2. 如何避免EventBus造成的内存泄漏? 3. 在Vue3中如何使用事件总线(因为Vue3移除了$on, $off等方法)?</think>在 Vue2 中使用 EventBus 时,在 layout 组件中监听事件后,**应当在组件的 `beforeDestroy` 生命周期钩子中移除监听**。这是为了避免内存泄漏和重复触发问题,具体原因和实现如下: ### 原因分析 1. **防止内存泄漏** 组件销毁时若不移除监听,EventBus 会持续持有对组件回调函数的引用,导致组件无法被垃圾回收[^2]。 2. **避免重复触发** 当组件被多次创建/销毁(如路由切换),未移除的监听器会累积,导致事件触发时回调函数被多次执行[^2][^3]。 3. **Layout 组件的特殊性** Layout 通常是根级组件,生命周期与整个应用一致。若不显式移除监听,其事件监听器会持续存在于整个应用生命周期中[^4]。 ### 正确实现方式 在 layout 组件中添加以下代码: ```javascript export default { created() { // 监听事件 this.$EventBus.$on("custom-event", this.handleEvent); }, beforeDestroy() { // 移除监听 this.$EventBus.$off("custom-event", this.handleEvent); }, methods: { handleEvent(payload) { console.log("事件触发:", payload); } } } ``` ### 关键注意事项 1. **精确移除监听** `$off` 需指定**事件名和回调函数引用**。若省略回调参数,会移除该事件的所有监听器[^3]: ```javascript // 正确:移除指定回调 this.$EventBus.$off("custom-event", this.handleEvent); // 谨慎:移除事件所有监听器 this.$EventBus.$off("custom-event"); ``` 2. **避免匿名函数** 若在 `$on` 中使用匿名函数,将无法在 `$off` 中引用同一函数: ```javascript // 错误示例(无法移除) this.$EventBus.$on("event", () => {...}); ``` 3. **全局 EventBus 管理** 建议封装独立模块(参考引用[3][^3][^5]): ```javascript // event-bus.js import Vue from 'vue'; export default new Vue(); ``` ### 替代方案建议 对于常驻的 layout 组件,若事件只需触发一次,可使用 `$once`: ```javascript created() { this.$EventBus.$once("one-time-event", this.handleEvent); } // 无需手动移除,触发后自动销毁 ``` --- ### 相关问题 1. **EventBus 导致回调函数重复执行该如何排查和修复?** > 此问题通常由未移除的监听器累积引起。可通过在 `beforeDestroy` 中添加移除逻辑解决,同时使用 Vue Devtools 检查事件监听器数量。 2. **Vue3 中如何替代 EventBus?** > Vue3 移除了 `$on/$off` API,推荐使用 `mitt` 或 `tiny-emitter` 等第三方库(参考引用[5][^5]),或改用 `provide/inject` 进行跨组件通信。 3. **如何确保 EventBus 在大型项目中可维护?** > 建议: > - 统一事件名常量管理 > - 为每个事件编写类型定义(TypeScript) > - 在路由守卫中统一检查残留监听器 4. **EventBus 与 Vuex 如何选择?** > EventBus 适合简单事件通知(如 UI 状态同步),Vuex 适合全局状态管理。关键区别在于: > - EventBus 无状态存储能力 > - Vuex 提供状态追踪和调试工具 > (参考引用[4][^4]中通信方案对比) [^1]: 移除事件监听的操作方法 [^2]: 组件销毁前需移除监听以避免重复触发 [^3]: EventBus 封装实现及 API 说明 [^4]: Vue 组件通信方案对比 [^5]: mitt 库在 Vue 中的封装实践
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值