Android Service 与 Activity / Fragment 的几种通信方式

更新日期: 2023-03-15 阅读次数: 1880 字数: 675 分类: Android

由于要实现切换到 Android 系统桌面时,蓝牙对讲功能依然可以使用,所以把主要的语音通信逻辑都放到了前台服务中,即 Foreground Service 中。但是,需要在打开对应的 Activity / Fragment 时,可以同步 Service 中的状态,及语音波形显示。这时就需要一种方式,能及时将 Service 中的变量状态发生变化时,及时通知 Activity / Fragment。

查了几种方案,最终选择了 LiveData。

LocalBroadcastManager

即,单个应用内部的广播。

LocalBroadcastManager.sendBroadcast 方法会将广播发送给与发送器位于同一应用中的接收器。 如果您不需要跨应用发送广播,请使用本地广播。这种实现方法的效率更高(无需进行进程间通信), 而且您无需担心其他应用在收发您的广播时带来的任何安全问题。

但是,现实是,LocalBroadcastManager 已经被废弃。官方推荐使用 LiveData 代替。

LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app: any component may listen events from any other. You can replace usage of LocalBroadcastManager with other implementation of observable pattern, depending on your usecase suitable options may be androidx.lifecycle.LiveData or reactive streams.

IBinder

大概意思是可以在 activity 中获取一个 Service 示例,然后进行操作。但是看上去代码太复杂了,不想尝试。

LiveData

LiveData 是一个可观察的数据持有者类,与常规的 Observable 不同, LiveData 可感知 Activity、Fragment、Service 的生命周期, 确保 LiveData 仅更新处于活动生命周期状态的组件观察者。 如果应用程序组件观察者所处的状态是 STARTED 或 RESUMED, 则 LiveData 认为该组件处于活跃状态,该组件会收到 LiveData 的数据更新, 而其他注册的组件观察者将不会收到任何数据更新。

看起来就非常适合 Service 向 Activity / Fragment 发送数据,毕竟 Service 的生命周期比这两个要长。 我本来以为 LiveData 只能用在 ViewModel 中,看来不是这样。

Service 中 java 实现:

public static FeatureAudio mAudio;
// 用于 fragment 中监听
public static MutableLiveData<Boolean> audioReady = new MutableLiveData<>(false);  
...
// 通知 fragment, mAudio 已准备好,可以监听了,用来更新 plot 波形
audioReady.postValue(true);

fragment 中监听 Servie 中的 LiveData 数据变化:

@Override
public void onResume() {
	super.onResume();
	NodeConnectionService.audioReady.observe(this, ready -> {
		Log.d(TAG, "mAudio ready status: " + ready);
		if (ready && NodeConnectionService.mAudio != null) {
			NodeConnectionService.mAudio.addFeatureListener(mUpdatePlot);
			mWaveformViewIn.startPlotting();
	   }
   });
}

setValue V.S. postValue

service 中使用 setValue 时,报错:

java.lang.IllegalStateException: Cannot invoke setValue on a background thread

setValue 改成 postValue

参考

  • Android LiveData
  • https://developer.android.com/reference/androidx/localbroadcastmanager/content/LocalBroadcastManager
  • https://stackoverflow.com/questions/74264850/localbroadcastmanager-is-now-deprecated-how-to-send-data-from-service-to-activi

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式