zoukankan      html  css  js  c++  java
  • EventBus使用的简介

    写在前面

    曾经我们做组件间的消息分发更新,通常会採用观察者模式。或者接口数据回调的相关方式,可是这种做法尽管能够解决我们的问题。可是组件之间的耦合相当严重,并且代码也不易阅读和维护,为了解决这种问题,我们能够使用消息总线EventBus框架。
    EventBus是一款针对Android优化的公布/订阅事件总线。主要特点例如以下:替代Intent,Handler,broadcast在Fragment。Activity。Service。线程之间传递消息。开销小,代码优雅,以及将发送者和接受者解耦。
    开源地址:https://github.com/greenrobot/EventBus

    EventBus简单使用方式(官网给的3步走,我这里细分了5步):

    • 1、项目增加依赖。在项目中的build.gradle中增加以下代码:
    compile 'org.greenrobot:eventbus:3.0.0'
    • 2、定义消息事件对象
    public class MessageEventOne {
        public final String message;
    
        public MessageEventOne(String message) {
            this.message = message;
        }
    }
    • 3、订阅者注冊到EventBUs以及配置事件接受方法
     EventBus.getDefault().register(this);
    
    //Declare your subscribing method:
    @Subscribe
    public void onEvent(AnyEventType event) {/* Do something */};
    • 4、公布这发送消息
     EventBus.getDefault().post(new MessageEventOne("Hello everyone!"));
    • 5、反注冊EventBus
    //这个是官网给的反注冊在stop方法中
    @Override
    public void onStop() {
       EventBus.getDefault().unregister(this);
        super.onStop();
    }
    //依据自己的须要,这里我的这个demo中使用的是
        @Override
        protected void onDestroy() {
            super.onDestroy();
            EventBus.getDefault().unregister(this);
        }

    好了。既然有了以上的五步实现方式,那么我们就简单的实现以下吧:
    在这里首先提示一点。例如以下图:

    看下代码MainActivity.java:

    package com.example.eventbusdemo;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    import org.greenrobot.eventbus.EventBus;
    import org.greenrobot.eventbus.Subscribe;
    import org.greenrobot.eventbus.ThreadMode;
    
    //import de.greenrobot.event.EventBus;
    
    public class MainActivity extends AppCompatActivity {
        private Button mButton1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            EventBus.getDefault().register(this);
            setContentView(R.layout.activity_main);
            initViews();
        }
    
        private void initViews() {
            mButton1 = (Button) findViewById(R.id.button1);
            mButton1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    startActivity(new Intent(MainActivity.this, Main2Activity.class));
                }
            });
        }
    
        /*@Subscribe
        public void onMessageEvent(MessageEventOne event) {
            Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
        }*/
    
        /**
         * 该方法会在UI线程中运行,接受事件同一时候会在UI线程中运行。这样我们能够在改方法中直接更新UI
         *
         * @param event
         */
        @Subscribe @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(MessageEventOne event) {
            Toast.makeText(this, "接收到消息:" + event.message, Toast.LENGTH_SHORT).show();
        }
    
    
    /*
        @Override
        protected void onStop() {
            super.onStop();
            EventBus.getDefault().unregister(this);
        }*/
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            EventBus.getDefault().unregister(this);
        }
    
    }
    

    Main2Activity.java:

    package com.example.eventbusdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import org.greenrobot.eventbus.EventBus;
    
    //import de.greenrobot.event.EventBus;
    
    
    public class Main2Activity extends AppCompatActivity {
    
        private Button button1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);
            initialize();
        }
        private void initialize() {
    
            button1 = (Button) findViewById(R.id.button1);
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d("wuyinlei", "Main2Activity当前线程" + Thread.currentThread()+toString());
                    EventBus.getDefault().post(new MessageEventOne("Hello everyone!"));
    
                    Main2Activity.this.finish();
                }
            });
    
        }
    }
    

    布局代码就更简单了,就有一个button。在这里就不多说了
    我们直接看下结果吧:

    这里写图片描写叙述

    使用是不是非常easy哈,接下来我们来看下EventBus里面的几个ThreadMode:

    POSTING
     PostThread :默认的 ThreadMode,表示在运行 Post 操作的线程直接调用订阅者的事件响应方法,
     不论该线程是否为主线程(UI 线程)。

    当该线程为主线程时,响应方法中不能有耗时操作, 否则有卡主线程的风险。适用场景: 对于是否在主线程运行无要求,但若 Post 线程为主线程。 不能耗时的操作 ; MAIN MainThread :在主线程中运行响应方法。假设公布线程就是主线程,则直接调用订阅者的事件响应方法, 否则通过主线程的 Handler 发送消息在主线程中处理——调用订阅者的事件响应函数。

    显然。 MainThread 类的方法也不能有耗时操作,以避免卡主线程。

    适用场景: 必须在主线程运行的操作 。 BACKGROUND BackgroundThread :在后台线程中运行响应方法。

    假设公布线程 不是 主线程,则直接调用订阅者的 事件响应函数,否则启动 唯一的 后台线程去处理。由于后台线程是唯一的,当事件超过一个的时候。 它们会被放在队列中依次运行,因此该类响应方法尽管没有 PostThread 类和 MainThread 类方法 对性能敏感。但最好不要有重度耗时的操作或太频繁的轻度耗时操作。以造成其它操作等待。适用场景: 操作轻微耗时且不会过于频繁 。即一般的耗时操作都能够放在这里; ASYNC Async :不论公布线程是否为主线程,都使用一个空暇线程来处理。和 BackgroundThread 不同的是 , Async 类的全部线程是相互独立的,因此不会出现卡线程的问题。适用场景: 长耗时操作, 比如网络訪问 。

    我也试过了。仅仅要指定ThreadMode,方法名字能够自定义的。以下我们来看下怎么使用吧。

    我们首先来看下怎么区分是谁发送的消息,这个时候我们在定义一个消息事件对象:

    public class MessageEventTwo {
        public final String message;
    
        public MessageEventTwo(String message) {
            this.message = message;
        }
    }

    我们在Main2Activity中增加一个button。来測试一下:

     button2 = (Button) findViewById(R.id.button2);
            button2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    EventBus.getDefault().post(new MessageEventTwo("我是第二个消息"));
                    Main2Activity.this.finish();
                }
            });

    我们来看下运行结果:这里写图片描写叙述
    能够看到。消息传递是不会混乱的。为什么呢,由于我们在接受消息的时候,已经指定了消息事件

     @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(MessageEventOne event) {
            Toast.makeText(this, "接收到消息:" + event.message, Toast.LENGTH_SHORT).show();
        }
    
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(MessageEventTwo event) {
            Toast.makeText(this, "接收到消息:" + event.message, Toast.LENGTH_SHORT).show();
        }
    

    在这里说一点,假设没有在接受消息方法上指定,那就是默认的模式,就是在post消息的线程中处理(我刚開始没有指定,測试其它几个的时候,都是在post线程中。找了好久也不知道,最后看了源代码知道了这几个模式 )

     @Subscribe(threadMode = ThreadMode.MAIN)还有其它的模式

    好了。我们来看下其它几种模式:

     /**
         * 使用该方法作为订阅函数表示post消息事件和接受消息事件在同一个线程中
         *
         * @param event
         */
        @Subscribe(threadMode = ThreadMode.POSTING)
        public void onEvent(MessageEventOne event) {
            Log.d("wuyinlei", "onEvent当前线程" + Thread.currentThread() + toString());
            //Toast.makeText(this, "接收到消息onEvent:" + event.message, Toast.LENGTH_SHORT).show();
        }
     /**
         * 使用该方法,假设事件在UI线程中发出来。该方法会在子线程中运行,假设是从子线程中发出来消息,该方法会在子线程中运行
         *
         * @param event
         */
        @Subscribe(threadMode = ThreadMode.BACKGROUND)
        public void onEventBackgroundThread(MessageEventOne event) {
            Log.d("wuyinlei", "onEventBackgroundThread当前线程" + Thread.currentThread() + toString());
           // Toast.makeText(this, "接收到消息onEvent:" + event.message, Toast.LENGTH_SHORT).show();
    
        }
    
        /**
         * 使用该方法,会在创建新的子线程中运行
         *
         * @param event
         */
        @Subscribe(threadMode = ThreadMode.ASYNC)
        public void Async(MessageEventOne event) {
            Log.d("wuyinlei", "onEventAsync当前线程" + Thread.currentThread() + toString());
           // Toast.makeText(this, "接收到消息onEvent:" + event.message, Toast.LENGTH_SHORT).show();
    
        }
    

    我们来看下log打印吧:

    好了,假设想要了解的很多其它,能够去看下源代码哈,假设有问题或者疑问或者见解,能够QQ:1069584784

  • 相关阅读:
    JAVA安卓和C# 3DES加密解密的兼容性问题(2013年8月修改版)
    eval绑定decimal数据后,如何去掉后面没有意义的0?
    Linq使用Group By经验总结
    mysql 分页存储过程 一次返回两个记录集(行的条数,以及行记录),DataReader的Read方法和NextResult方法
    把 HttpHandler.ashx 修改为 异步编程 异步操作
    td内容自动换行 ,td超过宽度显示点点点… , td 使用 overflow:hidden 无效,英文 数字 不换行 撑破div容器
    window.location.href = window.location.href 跳转无反应 a 超链接 onclick 点击跳转无反应
    C#怎么调用百度地图Web API
    .Net MVC 当前上下文中不存在名称“Style”
    无法使用备份文件 'D:20160512.bak',因为原先格式化该文件时所用扇区大小为 512,而目前所在设备的扇区大小为 4096
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7263802.html
Copyright © 2011-2022 走看看