热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidRxbus事件总线

我的视频课程:《FFmpeg打造Android万能音频播放器》最近在项目中使用了Rxjava和RxAndroid,确实感觉挺不错的,然后听说可以用RxBus来替换

我的视频课程:《FFmpeg打造Android万能音频播放器》


        最近在项目中使用了Rxjava和RxAndroid,确实感觉挺不错的,然后听说可以用RxBus来替换掉EventBus等事件分发的三方库,然后就上午找比较好的RxBus开源项目(以为是有统一标准的),然而后面才知道,RxBus没有绝对的,只是一种想法而已,借助Rxjava的特性来实现的。既然这样,我也就自己实现了一个(可以设置tag,并指定事件接收的线程类型),测试效果还是蛮不错的。先看效果图:


途中,在第一个activity中发送事件,并在其中接收到事件,文本框内容改变;打开第二个activity,发送相同tag的事件,所以第一个activity中也接收到了第二个activity发送的事件。

一:首先添加依赖库

dependencies {
    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
}
二:编写RxBus类

package com.ywl5320.rxbusdemo.RxBus;


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

import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
import rx.subjects.SerializedSubject;
import rx.subjects.Subject;

/**
 * Created by ywl on 2016/5/20.
 */
public class RxBus {

    private final Subject _bus = new SerializedSubject<>(PublishSubject.create());
    private final Map tags = new HashMap<>();

    private static RxBus rxbus;

    public static RxBus getInstance()
    {
        if(rxbus == null)
        {
            synchronized (RxBus.class) {
                if(rxbus == null) {
                    rxbus = new RxBus();
                }
            }
        }
        return rxbus;
    }

    /**
     * 发送事件消息
     * @param tag 用于区分事件
     * @param object 事件的参数
     */
    public void post(String tag, Object object)
    {
        _bus.onNext(object);
        if(!tags.containsKey(tag))
        {
            tags.put(tag, object);
        }
    }

    /**
     * 主线程中执行
     * @param tag
     * @param rxBusResult
     */
    public void toObserverableOnMainThread(final String tag, final RxBusResult rxBusResult) {

            _bus.observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1() {
                @Override
                public void call(Object o) {
                    if (tags.containsKey(tag)) {
                        rxBusResult.onRxBusResult(o);
                    }
                }
            });
    }

    /**
     * 子线程中执行
     * @param tag
     * @param rxBusResult
     */
    public void toObserverableChildThread(final String tag, final RxBusResult rxBusResult) {

        _bus.observeOn(Schedulers.io()).subscribe(new Action1() {
            @Override
            public void call(Object o) {
                if (tags.containsKey(tag)) {
                    rxBusResult.onRxBusResult(o);
                }
            }
        });
    }

    /**
     * 移除tag
     * @param tag
     */
    public void removeObserverable(String tag)
    {
            if(tags.containsKey(tag))
            {
                tags.remove(tag);
            }
    }

    /**
     * 退出应用时,清空资源
     */
    public void release()
    {
        tags.clear();
        rxbus = null;
    }

}

在RxBus类中,使用到了Subject引用网上的解释:“Subject在ReactiveX是作为observer和observerable的一个bridge或者proxy。因为它是一个观察者,所以它可以订阅一个或多个可观察对象,同时因为他是一个可观测对象,所以它可以传递和释放它观测到的数据对象,并且能释放新的对象。”

Subject表示一个同时是Observable和Observer的对象,所以Subject即使订阅者也是观察者,利用这个特性,我们就可以利用它发送和接收消息。Subject的onNext(Object)方法会向所有订阅者发送事件,但是我们在项目中一般都是点对点的发送,不希望其他无关的订阅者也接收到事件,所以在RxBus中添加了一个Map来管理事件的tag,来区别该事件来自哪里,将要去哪里。

为了接收时写更少的代码,写了一个回调函数来处理接收到的信息:

package com.ywl5320.rxbusdemo.RxBus;

/**
 * Created by ywl on 2016/5/20.
 */
public interface RxBusResult {

    /**
     * 事件回调接口
     * @param o
     */
    void onRxBusResult(Object o);

}


二:怎么使用

1、首先定义RxBus并初始化

private RxBus rxBus = RxBus.getInstance();
2、发送消息

btnsend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rxBus.post("first", new String("hello rxbus"));
            }
        });
其中,“first”即为区分事件的tag,第二个参数是发送的对象。

3、接收消息

rxBus.toObserverableOnMainThread("first", new RxBusResult() {
            @Override
            public void onRxBusResult(Object o) {
                final String msg = (String)o;
                mtvmsg.setText("first收到消息;" + msg);
                Toast.makeText(MainActivity.this, "收到消息;" + msg, Toast.LENGTH_SHORT).show();
            }
        });
这里指定在主线程中接收tag为“first”的消息并处理。

这样发送接收就都完成了,但是为了更好的管理tag,我们在退出时最好把相应的tag清除掉,如:

@Override
    protected void onDestroy() {
        super.onDestroy();
        rxBus.removeObserverable("first");
    }

最后:在应用程序完全退出时还需调用rxBus.release()方法释放资源(也避免了一个问题:就是如果不释放,第二次启动应用时,不能更新UI,可能是rxBus和第二次启动的应用不在同一个进程中造成的,因为第一次退出应用时,rxBus是没有销毁的,第二次不会重新创建,所以导致了这个问题)

最后把MainActivity和SecondActivity中代码贴出来:

package com.ywl5320.rxbusdemo;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.ywl5320.rxbusdemo.RxBus.RxBus;
import com.ywl5320.rxbusdemo.RxBus.RxBusResult;

public class MainActivity extends AppCompatActivity {

    private Button btnsend;
    private Button btnsecond;
    private TextView mtvmsg;

    private RxBus rxBus = RxBus.getInstance();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnsend = (Button) findViewById(R.id.btn_send);
        btnsecOnd= (Button) findViewById(R.id.btn_second);
        mtvmsg = (TextView) findViewById(R.id.tv_msg);

        btnsend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rxBus.post("first", new String("hello rxbus"));
            }
        });

        btnsecond.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                MainActivity.this.startActivity(intent);
            }
        });

        rxBus.toObserverableOnMainThread("first", new RxBusResult() {
            @Override
            public void onRxBusResult(Object o) {
                final String msg = (String)o;
                mtvmsg.setText("first收到消息;" + msg);
                Toast.makeText(MainActivity.this, "收到消息;" + msg, Toast.LENGTH_SHORT).show();
            }
        });

        rxBus.toObserverableOnMainThread("second", new RxBusResult() {
            @Override
            public void onRxBusResult(Object o) {
                String msg = (String)o;
                mtvmsg.setText("second收到消息;" + msg);
                Toast.makeText(MainActivity.this, "second收到消息;" + msg, Toast.LENGTH_SHORT).show();
            }
        });

    }

    /**
     * 退出时,释放rxbus
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        rxBus.release();
    }
}

package com.ywl5320.rxbusdemo;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import com.ywl5320.rxbusdemo.RxBus.RxBus;

/**
 * Created by ywl on 2016/5/20.
 */
public class SecondActivity extends AppCompatActivity {

    private Button mbtnsend;
    private RxBus rxBus = RxBus.getInstance();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);

        mbtnsend = (Button) findViewById(R.id.btn_send);
        mbtnsend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rxBus.post("second", new String("第二个页面的数据"));
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        rxBus.removeObserverable("first");
    }
}

这样就完成了RxBus工具类的编写  Demo下载地址 (注:demo的RxBus有Bug,就是不能同时两个接收同一个发送的消息,这里可以以博客中为准,博客中已经修改了,可以对比下改了什么哟 哈哈哈)。

github:https://github.com/wanliyang1990/rxbusDemo










推荐阅读
  • 本文探讨了Java编程语言中常用的两个比较操作符==和equals方法的区别及其应用场景。通过具体示例分析,帮助开发者更好地理解和使用这两个概念,特别是在处理基本数据类型和引用数据类型的比较时。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 本文介绍了一种在 Android 开发中动态修改 strings.xml 文件中字符串值的有效方法。通过使用占位符,开发者可以在运行时根据需要填充具体的值,从而提高应用的灵活性和可维护性。 ... [详细]
  • selenium通过JS语法操作页面元素
    做过web测试的小伙伴们都知道,web元素现在很多是JS写的,那么既然是JS写的,可以通过JS语言去操作页面,来帮助我们操作一些selenium不能覆盖的功能。问题来了我们能否通过 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • 本文探讨了如何利用 Android 的 Movie 类来展示 GIF 动画,并详细介绍了调整 GIF 尺寸以适应不同布局的方法。同时,提供了相关的代码示例和注意事项。 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 本文分享了作者在不同版本的Ubuntu系统上尝试编译VLC for Android的经历,包括遇到的技术难题及解决方案,旨在帮助开发者避免常见的编译问题。 ... [详细]
  • 在Java开发中,如何利用ProcessBuilder类调用外部程序是一个常见的需求。本文将详细介绍ProcessBuilder类的使用方法,并提供示例代码帮助你更好地理解和应用。 ... [详细]
  • 在Android平台中,播放音频的采样率通常固定为44.1kHz,而录音的采样率则固定为8kHz。为了确保音频设备的正常工作,底层驱动必须预先设定这些固定的采样率。当上层应用提供的采样率与这些预设值不匹配时,需要通过重采样(resample)技术来调整采样率,以保证音频数据的正确处理和传输。本文将详细探讨FFMpeg在音频处理中的基础理论及重采样技术的应用。 ... [详细]
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • 在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转
    本文探讨了在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转的技术细节。通过详细分析Swscale的工作原理和实际应用,展示了如何在Android环境中高效地进行图像格式转换。此外,还介绍了FFmpeg的全平台编译过程,包括x264和fdk-aac的集成,并在Ubuntu系统中配置Nginx和Nginx-RTMP-Module以支持直播推流服务。这些技术的结合为音视频处理提供了强大的支持。 ... [详细]
  • 本文介绍如何通过Java代码调用阿里云短信服务API来实现短信验证码的发送功能,包括必要的依赖添加和关键代码示例。 ... [详细]
author-avatar
石奉帝时尚_719_273
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有