如何从Service向Activity传递数据?求替代废弃LocalBroadcastManager的示例
Service 向 Activity 传递数据的几种实现方案
方案一:使用 LiveData(推荐)
LiveData 是 Jetpack 组件的一部分,自带生命周期感知能力,能自动适配 Activity 生命周期变化,避免内存泄漏,是当前最推荐的实现方式。
实现代码
- 定义共享的 ViewModel(用于持有可观察数据)
class DataSharedViewModel(application: Application) : AndroidViewModel(application) { // 可观察的数据容器,支持跨组件共享 val dataLiveData = MutableLiveData<String>() // 提供更新数据的方法,子线程中用 postValue 确保线程安全 fun updateData(data: String) { dataLiveData.postValue(data) } }
- Service 端代码
class MyService : Service() { private lateinit var sharedViewModel: DataSharedViewModel override fun onCreate() { super.onCreate() // 通过 Application 获取全局共享的 ViewModel 实例 sharedViewModel = ViewModelProvider( this, ViewModelProvider.AndroidViewModelFactory.getInstance(application) )[DataSharedViewModel::class.java] // 模拟后台线程持续生成并发送数据 Thread { repeat(10) { count -> Thread.sleep(1000) sharedViewModel.updateData("Service 发送的第 ${count+1} 条数据") } }.start() } override fun onBind(intent: Intent): IBinder? = null }
- Activity 端代码
class MainActivity : AppCompatActivity() { private lateinit var sharedViewModel: DataSharedViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 获取与 Service 同一实例的 ViewModel sharedViewModel = ViewModelProvider( this, ViewModelProvider.AndroidViewModelFactory.getInstance(application) )[DataSharedViewModel::class.java] // 观察数据变化,自动在主线程回调更新 UI sharedViewModel.dataLiveData.observe(this) { data -> findViewById<TextView>(R.id.tv_data).text = data } // 启动 Service startService(Intent(this, MyService::class.java)) } }
方案二:使用接口回调
适合需要实时交互的场景,需通过弱引用避免内存泄漏。
实现代码
- 定义回调接口
interface ServiceDataCallback { fun onDataReceived(data: String) }
- Service 端代码
class MyService : Service() { // 用弱引用存储回调,防止 Activity 销毁后内存泄漏 private val callbacks = mutableListOf<WeakReference<ServiceDataCallback>>() // 注册回调 fun registerCallback(callback: ServiceDataCallback) { callbacks.add(WeakReference(callback)) } // 移除回调 fun unregisterCallback(callback: ServiceDataCallback) { callbacks.removeAll { it.get() == callback } } override fun onCreate() { super.onCreate() Thread { repeat(10) { count -> Thread.sleep(1000) val data = "Service 发送的第 ${count+1} 条数据" // 遍历回调列表,发送数据 callbacks.forEach { ref -> ref.get()?.onDataReceived(data) } } }.start() } // 通过 Binder 让 Activity 获取 Service 实例 inner class MyBinder : Binder() { fun getService(): MyService = this@MyService } override fun onBind(intent: Intent): IBinder = MyBinder() }
- Activity 端代码
class MainActivity : AppCompatActivity(), ServiceDataCallback { private var myService: MyService? = null private var isServiceBound = false private val serviceConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { val binder = service as MyService.MyBinder myService = binder.getService() myService?.registerCallback(this@MainActivity) isServiceBound = true } override fun onServiceDisconnected(arg0: ComponentName) { isServiceBound = false myService?.unregisterCallback(this@MainActivity) myService = null } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 绑定 Service bindService(Intent(this, MyService::class.java), serviceConnection, Context.BIND_AUTO_CREATE) } override fun onDataReceived(data: String) { // 切换到主线程更新 UI runOnUiThread { findViewById<TextView>(R.id.tv_data).text = data } } override fun onDestroy() { super.onDestroy() // 解绑时移除回调,避免内存泄漏 if (isServiceBound) { myService?.unregisterCallback(this) unbindService(serviceConnection) } } }
方案三:使用 Messenger
适合跨进程通信场景(同进程也适用),通过 Handler 传递 Message 实现数据交互。
实现代码
- Service 端代码
class MyService : Service() { // Service 端的 Handler,处理来自 Activity 的消息 private val serviceHandler = Handler(Looper.getMainLooper()) { msg -> // 获取 Activity 的 Messenger,用于回复数据 val activityMessenger = msg.replyTo // 模拟后台发送数据 Thread { repeat(10) { count -> Thread.sleep(1000) val dataMsg = Message.obtain().apply { what = 1 // 消息标识,用于区分不同类型消息 obj = "Service 发送的第 ${count+1} 条数据" } try { activityMessenger?.send(dataMsg) } catch (e: RemoteException) { e.printStackTrace() } } }.start() true } private val messenger = Messenger(serviceHandler) override fun onBind(intent: Intent): IBinder = messenger.binder }
- Activity 端代码
class MainActivity : AppCompatActivity() { private var serviceMessenger: Messenger? = null private var isServiceBound = false // Activity 端的 Handler,处理来自 Service 的消息 private val activityMessenger = Messenger(object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when (msg.what) { 1 -> { val data = msg.obj as String findViewById<TextView>(R.id.tv_data).text = data } else -> super.handleMessage(msg) } } }) private val serviceConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { serviceMessenger = Messenger(service) isServiceBound = true // 发送消息给 Service,传递 Activity 的 Messenger val msg = Message.obtain().apply { replyTo = activityMessenger } try { serviceMessenger?.send(msg) } catch (e: RemoteException) { e.printStackTrace() } } override fun onServiceDisconnected(arg0: ComponentName) { serviceMessenger = null isServiceBound = false } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) bindService(Intent(this, MyService::class.java), serviceConnection, Context.BIND_AUTO_CREATE) } override fun onDestroy() { super.onDestroy() if (isServiceBound) { unbindService(serviceConnection) } } }
内容的提问来源于stack exchange,提问作者zeus
相关产品推荐
相关产品推荐

