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
相关产品推荐
相关产品推荐

