You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用内购买Server Notification实现及Pub/Sub实现指南求助

Android 应用内 Pub/Sub 实现指南

核心逻辑

应用内Pub/Sub(发布-订阅)是让组件间通过「主题」解耦通信的模式:发布者仅需往指定主题发送消息,订阅该主题的接收者会自动收到消息,无需直接持有对方引用,适合Activity/Fragment通信、跨页面状态通知这类场景。

方案一:自定义轻量消息总线(适合简单场景)

无需依赖第三方库,几十行代码就能实现:

1. 定义订阅者接口

先统一订阅者的规范,规定接收消息的方法:

interface Subscriber<T> {
    fun onMessageReceived(topic: String, data: T)
}

2. 实现消息总线核心类

用单例模式写一个消息管理类,负责维护订阅者列表和分发消息:

object MessageBus {
    // key为主题名,value为该主题下的所有订阅者
    private val subscribers = mutableMapOf<String, MutableList<Subscriber<*>>>()

    // 订阅指定主题
    fun <T> subscribe(topic: String, subscriber: Subscriber<T>) {
        subscribers.getOrPut(topic) { mutableListOf() }.add(subscriber)
    }

    // 取消订阅(必须在组件销毁时调用,防止内存泄漏)
    fun <T> unsubscribe(topic: String, subscriber: Subscriber<T>) {
        subscribers[topic]?.remove(subscriber)
    }

    // 往指定主题发布消息
    fun <T> publish(topic: String, data: T) {
        subscribers[topic]?.forEach { subscriber ->
            @Suppress("UNCHECKED_CAST")
            (subscriber as Subscriber<T>).onMessageReceived(topic, data)
        }
    }
}

3. 实际使用示例

比如在Fragment里订阅用户更新消息,在Activity里触发发布:

  • 订阅端(Fragment):
class UserFragment : Fragment(), Subscriber<String> {
    // 用常量定义主题,避免拼写错误
    private val TOPIC_USER_UPDATE = "topic_user_update"

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 订阅主题
        MessageBus.subscribe(TOPIC_USER_UPDATE, this)
    }

    // 收到消息后的处理逻辑
    override fun onMessageReceived(topic: String, data: String) {
        userInfoTv.text = "最新状态:$data"
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // 必须取消订阅,防止内存泄漏
        MessageBus.unsubscribe(TOPIC_USER_UPDATE, this)
    }
}
  • 发布端(Activity):
// 点击按钮发布消息
updateBtn.setOnClickListener {
    MessageBus.publish(TOPIC_USER_UPDATE, "张三已完成实名认证")
}

方案二:用Jetpack LiveData实现(推荐,自带生命周期感知)

利用LiveData的生命周期感知特性,无需手动取消订阅,自动避免内存泄漏,适合大多数场景:

1. 实现LiveData消息总线

object LiveDataBus {
    // 存储不同主题对应的LiveData
    private val bus = mutableMapOf<String, MutableLiveData<Any>>()

    // 根据主题获取对应的LiveData
    @Suppress("UNCHECKED_CAST")
    fun <T> getLiveData(topic: String): MutableLiveData<T> {
        return bus.getOrPut(topic) { MutableLiveData<Any>() } as MutableLiveData<T>
    }
}

2. 实际使用示例

  • 订阅端(Fragment):
class UserFragment : Fragment() {
    private val TOPIC_USER_UPDATE = "topic_user_update"

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 订阅主题,用viewLifecycleOwner绑定生命周期,自动在销毁时取消订阅
        LiveDataBus.getLiveData<String>(TOPIC_USER_UPDATE).observe(viewLifecycleOwner) { data ->
            userInfoTv.text = "最新状态:$data"
        }
    }
}
  • 发布端(Activity):
updateBtn.setOnClickListener {
    // 主线程用value,子线程用postValue
    LiveDataBus.getLiveData<String>(TOPIC_USER_UPDATE).value = "张三已完成实名认证"
}

注意事项

  • 自定义消息总线必须在组件销毁时手动取消订阅,否则会导致内存泄漏;
  • LiveData方案优先推荐,自带生命周期感知,减少手动操作;
  • 复杂场景如果需要更多线程控制,可考虑用RxJava的Subject,但要额外处理生命周期绑定;
  • 主题名建议用常量统一管理,避免拼写错误导致消息接收失败。

内容的提问来源于stack exchange,提问作者ArkaneKhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:47:02