返回顶部
首页 > 资讯 > 精选 >Android如何实现消息总线
  • 316
分享到

Android如何实现消息总线

2023-07-02 10:07:28 316人浏览 八月长安
摘要

这篇文章主要介绍“Android如何实现消息总线”,在日常操作中,相信很多人在Android如何实现消息总线问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android如何实现消息总线”的疑惑有所帮助!接下来

这篇文章主要介绍“Android如何实现消息总线”,在日常操作中,相信很多人在Android如何实现消息总线问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android如何实现消息总线”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、BroadcastReceiver 广播

我们再初入 Android 的时候都应该学过广播接收者,分为静态广播和动态注册广播,在高版本的 Android 中限制了我们一些静态广播的使用,不过我们还是能通过动态注册的方式获取一些系统的状态改变。像常用的电量变化、网络状态变化、短信发送接收的状态等等。

比如网络变化的监听:

    IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTioN);    application.getApplicationContext().reGISterReceiver(InstanceHolder.INSTANCE, intentFilter);

在消息中线中,我们可以使用本地广播来实现 LocalBroadcastManager 消息的通知。

    LocalBroadcastManager mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);        BroadcastReceiver  mLoginReceiver = new LoginSuccessReceiver();    mLocalBroadcastManager.registerReceiver(mLoginReceiver, new IntentFilter(Constants.ACTION_LOGIN_SUCCESS));    private class LoginSuccessReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            //刷新Home界面            refreshHomePage();                    //刷新未读信息            requestUnreadNum();        }    }    //记得要解绑对应的接收器    mLocalBroadcastManager.unregisterReceiver(mLoginReceiver);

这样就可以实现一个消息通知了。相比 EventBus 它的性能和空间的消耗都是较大的,并且只能固定在主线程运行。

二、EventBus

EventBus最大的特点就是简洁、解耦,可以直接传递我们自定义的消息Message。EventBus简化了应用程序内各组件间、组件与后台线程间的通信。记得2015年左右是非常火爆的。

EventBus的调度灵活,不依赖于 Context,使用时无需像广播一样关注 Context 的注入与传递。可继承、优先级、粘滞,是 EventBus 比之于广播的优势。几乎可以满足我们全部的需求。

最初的EventBus其实就是一个方法的集合与查找,核心是通过register方法把带有@Subscrib注解的方法和参数之类的东西全部放入一个List集合,然后通过post方法去这个list循环查找到符合条件的方法去执行。

如何使用EventBus,一共分5步:

  @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_event_bus);        EventBus.getDefault().register(MainActivity.this);  //1.注册广播    }
  @Override    protected void onDestroy() {        super.onDestroy();        EventBus.getDefault().unregister(MainActivity.this); //2.解注册广播    }
public class MessageEvent {    public String name;    public MessageEvent(String name) {        this.name = name;    }}
    @OnClick({R.id.bt_eventbus_send_main, R.id.bt_eventbus_send_sticky})    public void onClick(View view) {        switch (view.getId()) {            case R.id.bt_eventbus_send_main:                //4.发送消息                EventBus.getDefault().post(new MessageEvent("我是主页面发送过来的消息"));                finish();                break;        }    }
       @Subscribe(threadMode = ThreadMode.MAIN)   //主线程执行    public void MessageEventBus(MessageEvent event) {        //5。显示接受到的消息        mTvEventbusResult.setText(event.name);    }

EventBus的性能开销其实不大,EventBus2.4.0 版是利用反射来实现的,后来改成 APT 实现之后会好很多。主要问题是需要定义很多的消息对象,消息太多之后就感觉管理起来很麻烦。当消息太多之后容器内部的查找会出现性能瓶颈。

就算如此 EventBus 也是值得大家使用的。

三、RxBus

RxBus是基于RxJava实现的,强大是强大,但是学习成本比较高,需要额外导入RxJava RxAndroid等库,这些库体积还是较大的。可以实现异步的消息等。

本身的实现是很简单的:

public class RxBus {    private volatile static RxBus mDefaultInstance;    private final Subject<Object> mBus;    private RxBus() {        mBus = PublishSubject.create().toSerialized();    }    public static RxBus getInstance() {        if (mDefaultInstance == null) {            synchronized (RxBus.class) {                if (mDefaultInstance == null) {                    mDefaultInstance = new RxBus();                }            }        }        return mDefaultInstance;    }        public void post(Object event) {        mBus.onNext(event);    }        public <T> Observable<T> toObservable(final Class<T> eventType) {        return mBus.ofType(eventType);    }        public boolean hasObservers() {        return mBus.hasObservers();    }    public void reset() {        mDefaultInstance = null;    }}

定义消息对象:

public class MsgEvent {    private String msg;    public MsgEvent(String msg) {        this.msg = msg;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }}

发送与接收:

RxBus.getInstance().toObservable(MsgEvent.class).subscribe(new Observer<MsgEvent>() {            @Override            public void onSubscribe(Disposable d) {                            }            @Override            public void onNext(MsgEvent msgEvent) {                //处理事件            }            @Override            public void onError(Throwable e) {                              }            @Override            public void onComplete() {            }        });RxBus.getInstance().post(new MsgEvent("Java"));

缺点是容易内存泄露,我们需要使用rxlifecycle 或者使用CompositeDisposable 自己对生命周期进行处理解绑。

四、LiveDataBus

官方出了AndroidX jetpack 内部包含LiveData,它可以感知并遵循Activity、Fragment或Service等组件的生命周期。

为什么要使用LiveDataBus,正是基于LiveData对组件生命周期可感知的特点,因此可以做到仅在组件处于生命周期的激活状态时才更新UI数据。

一个简单的LiveDataBus的实现:

public final class LiveDataBus {    private final Map<String, BusMutableLiveData<Object>> bus;     private LiveDataBus() {        bus = new HashMap<>();    }     private static class SingletonHolder {        private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();    }     public static LiveDataBus get() {        return SingletonHolder.DEFAULT_BUS;    }     public <T> MutableLiveData<T> with(String key, Class<T> type) {        if (!bus.containsKey(key)) {            bus.put(key, new BusMutableLiveData<>());        }        return (MutableLiveData<T>) bus.get(key);    }     public MutableLiveData<Object> with(String key) {        return with(key, Object.class);    }     private static class ObserverWrapper<T> implements Observer<T> {         private Observer<T> observer;         public ObserverWrapper(Observer<T> observer) {            this.observer = observer;        }         @Override        public void onChanged(@Nullable T t) {            if (observer != null) {                if (isCallOnObserve()) {                    return;                }                observer.onChanged(t);            }        }         private boolean isCallOnObserve() {            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();            if (stackTrace != null && stackTrace.length > 0) {                for (StackTraceElement element : stackTrace) {                    if ("android.arch.lifecycle.LiveData".equals(element.getClassName()) &&                            "observeForever".equals(element.getMethodName())) {                        return true;                    }                }            }            return false;        }    }     private static class BusMutableLiveData<T> extends MutableLiveData<T> {         private Map<Observer, Observer> observerMap = new HashMap<>();         @Override        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {            super.observe(owner, observer);            try {                hook(observer);            } catch (Exception e) {                e.printStackTrace();            }        }         @Override        public void observeForever(@NonNull Observer<T> observer) {            if (!observerMap.containsKey(observer)) {                observerMap.put(observer, new ObserverWrapper(observer));            }            super.observeForever(observerMap.get(observer));        }         @Override        public void removeObserver(@NonNull Observer<T> observer) {            Observer realObserver = null;            if (observerMap.containsKey(observer)) {                realObserver = observerMap.remove(observer);            } else {                realObserver = observer;            }            super.removeObserver(realObserver);        }         private void hook(@NonNull Observer<T> observer) throws Exception {            //get wrapper's version            Class<LiveData> classLiveData = LiveData.class;            Field fieldObservers = classLiveData.getDeclaredField("mObservers");            fieldObservers.setAccessible(true);            Object objectObservers = fieldObservers.get(this);            Class<?> classObservers = objectObservers.getClass();            Method methodGet = classObservers.getDeclaredMethod("get", Object.class);            methodGet.setAccessible(true);            Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);            Object objectWrapper = null;            if (objectWrapperEntry instanceof Map.Entry) {                objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();            }            if (objectWrapper == null) {                throw new NullPointerException("Wrapper can not be bull!");            }            Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();            Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");            fieldLastVersion.setAccessible(true);            //get livedata's version            Field fieldVersion = classLiveData.getDeclaredField("mVersion");            fieldVersion.setAccessible(true);            Object objectVersion = fieldVersion.get(this);            //set wrapper's version            fieldLastVersion.set(objectWrapper, objectVersion);        }    }}

注册与发送:

LiveDataBus.get()        .with("key_test", String.class)        .observe(this, new Observer<String>() {            @Override            public void onChanged(@Nullable String s) {            }        });LiveDataBus.get().with("key_test").setValue(s);

LiveDataBus已经算是很好用的,自动注册解绑,根据Key传递泛型T对象,容易查找对应的接收者,也可以实现可见的触发和直接触发,可以实现跨进程,

LiveData有几点不足,只能在主线程更新数据,操作符无法转换数据,基于 Android api 实现的,换一个平台无法适应,基于这几点又开发出了FlowBus。

五、FlowBus

很多人都说Flow 的出现导致 LiveData 没那么重要了,就是因为 LiveData 的场景 都可以使用 Flow 平替了,还能更为的强大和灵活。

StateFlow 可以 替代ViewModel中传递数据,SharedFlow 可以实现事件总线。(这两者的异同如果大家有兴趣,我可以单独开一篇讲下)。

SharedFlow 就是一种热流,可以实现一对多的关系,其构造方法支持天然支持普通的消息发送与粘性的消息发送。一般我们FlowBus都是基于 SharedFlow 来实现:

object FlowBus {    private val busMap = mutableMapOf<String, EventBus<*>>()    private val busStickMap = mutableMapOf<String, StickEventBus<*>>()    @Synchronized    fun <T> with(key: String): EventBus<T> {        var eventBus = busMap[key]        if (eventBus == null) {            eventBus = EventBus<T>(key)            busMap[key] = eventBus        }        return eventBus as EventBus<T>    }    @Synchronized    fun <T> withStick(key: String): StickEventBus<T> {        var eventBus = busStickMap[key]        if (eventBus == null) {            eventBus = StickEventBus<T>(key)            busStickMap[key] = eventBus        }        return eventBus as StickEventBus<T>    }    //真正实现类    open class EventBus<T>(private val key: String) : LifecycleObserver {        //私有对象用于发送消息        private val _events: MutableSharedFlow<T> by lazy {            obtainEvent()        }        //暴露的公有对象用于接收消息        val events = _events.assharedFlow()        open fun obtainEvent(): MutableSharedFlow<T> = MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)        //主线程接收数据        fun register(lifecycleOwner: LifecycleOwner, action: (t: T) -> Unit) {            lifecycleOwner.lifecycle.addObserver(this)            lifecycleOwner.lifecycleScope.launch {                events.collect {                    try {                        action(it)                    } catch (e: Exception) {                        e.printStackTrace()                        YYLogUtils.e("FlowBus - Error:$e")                    }                }            }        }        //协程中发送数据        suspend fun post(event: T) {            _events.emit(event)        }        //主线程发送数据        fun post(scope: CoroutineScope, event: T) {            scope.launch {                _events.emit(event)            }        }        //自动销毁        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)        fun onDestroy() {            YYLogUtils.w("FlowBus - 自动onDestroy")            val subscriptCount = _events.subscriptionCount.value            if (subscriptCount <= 0)                busMap.remove(key)        }    }    class StickEventBus<T>(key: String) : EventBus<T>(key) {        override fun obtainEvent(): MutableSharedFlow<T> = MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)    }}

发送与接收消息

    // 主线程-发送消息    FlowBus.with<String>("test-key-01").post(this@Demo11OneFragment2.lifecycleScope, "Test Flow Bus Message")
    // 接收消息    FlowBus.with<String>("test-key-01").register(this) {            LogUtils.w("收到FlowBus消息 - " + it)        }

发送粘性消息

 FlowBus.withStick<String>("test-key-02").post(lifecycleScope, "Test Stick Message")
   FlowBus.withStick<String>("test-key-02").register(this){            LogUtils.w("收到粘性消息:$it")        }

Log如下:

Android如何实现消息总线

Android如何实现消息总线

到此,关于“Android如何实现消息总线”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Android如何实现消息总线

本文链接: https://lsjlt.com/news/341093.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android如何实现消息总线
    这篇文章主要介绍“Android如何实现消息总线”,在日常操作中,相信很多人在Android如何实现消息总线问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android如何实现消息总线”的疑惑有所帮助!接下来...
    99+
    2023-07-02
  • Android实现消息总线的几种方式详解
    目录前言一、BroadcastReceiver 广播二、EventBus三、RxBus四、LiveDataBus五、FlowBus总结前言 消息总线又叫事件总线,为什么我们需要一个消...
    99+
    2024-04-02
  • 基于kafka实现SpringCloudBus消息总线
    目录一、什么是消息总线二、整合消息总线实现配置自动刷新2.1 面向客户端基本架构2.2 面向服务端的架构三、利用kafka实现消息总线3.1 Spring Boot 整合kafka3...
    99+
    2024-04-02
  • SpringcloudBus消息总线原理是实现详解
    目录springcloud Bus什么是springcloud Bus什么是消息总线Bus实现自动刷新的原理RabbitMQ的下载配置ErlangRabbitMQBus动态刷新全局广...
    99+
    2024-04-02
  • 基于kafka怎么实现Spring Cloud Bus消息总线
    这篇文章主要介绍“基于kafka怎么实现Spring Cloud Bus消息总线”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于kafka怎么实现Spring Clo...
    99+
    2023-06-30
  • 解析Spring Cloud Bus消息总线
    概念 我们使用配置中心时,当配置中心的配置发生了变化,我们就要发送一个post请求给客户端,让它重新去拉取新的的配置。当客户端有很多时,并且还是使用同一份配置文件,这样当配置中心的配...
    99+
    2024-04-02
  • maven如何实现kafka消息消费
    要使用 Maven 实现 Kafka 消息消费,需要按照以下步骤进行操作:1. 在 Maven 项目的 `pom.xml` 文件中添...
    99+
    2023-09-14
    maven kafka
  • Android 消息机制问题总结
    Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的。下面...
    99+
    2022-06-06
    消息机制 Android
  • Android消息机制Handler用法总结
    1.简述 Handler消息机制主要包括: MessageQueue、 Handler、 Looper、Message。 Message:需要传递的消息,可以传递数据; ...
    99+
    2024-04-02
  • redis如何实现消息队列
    Redis可以实现消息队列的功能,常用的实现方式是使用Redis的List数据结构来存储消息队列中的消息。具体实现步骤如下: 将...
    99+
    2024-04-22
    Redis
  • Android几种消息推送方案总结
    首先看一张国内Top500 Android应用中它们用到的第三方推送以及所占数量: 现在总结下Android平台下几种推送方案的基本情况以及优缺点: 一、使用GCM(Goog...
    99+
    2022-06-06
    Android
  • java怎么配置中心和消息总线
    这篇文章主要介绍“java怎么配置中心和消息总线”,在日常操作中,相信很多人在java怎么配置中心和消息总线问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java怎么配置中心和消息总线”的疑惑有所帮助!接下来...
    99+
    2023-06-05
  • jquery如何实现新消息提示
    本篇内容介绍了“jquery如何实现新消息提示”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • 如何用PHP实现消息推送
     什么是消息推送 通过服务器自动推送消息到客户端(浏览器,APP,微信)的应用技术。  为什么要使用消息推送技术 通常情况下都是用户发送请求浏览器显示用户需要的信息。推送技术通过自动传送信息给用户,来减少用于网络上搜索的时间。它根据用户的兴...
    99+
    2023-08-31
    php 开发语言 websocket
  • Redis中如何实现消息队列和延时消息队列
    这篇文章将为大家详细讲解有关Redis中如何实现消息队列和延时消息队列,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。list的几个命令lpush (left push)由...
    99+
    2024-04-02
  • JavaScript如何实现事件总线
    这篇文章主要讲解了“JavaScript如何实现事件总线”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript如何实现事件总线”吧!介绍Event Bus 事件总线,通...
    99+
    2023-06-30
  • android线程消息机制之Handler详解
    android线程消息机制主要由Handler,Looper,Message和MessageQuene四个部分组成。平常在开发中,我们常用来在子线程中通知主线程来更新,其实整个安卓生命周期的驱动都是通过Handler(ActivityThr...
    99+
    2023-05-30
    android 线程消息机制 handler
  • js如何实现消息滚动效果
    这篇文章主要为大家展示了“js如何实现消息滚动效果”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js如何实现消息滚动效果”这篇文章吧。1.实现的中心思想,如图所...
    99+
    2024-04-02
  • thinkphp如何实现友盟消息推送
    这篇文章主要为大家展示了“thinkphp如何实现友盟消息推送”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“thinkphp如何实现友盟消息推送”这篇文章吧。上...
    99+
    2024-04-02
  • 如何使用redis实现消息队列
    使用redis实现消息队列的示例:redis的pubsub功能实现发布订阅模式,代码:import redisclass Task(object):def __init__(self):self.rcon = redis.StrictRed...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作