实现Service和UI通信,并且能够手动回收的解决方案——共享ViewModel
完整实现方案
1. 创建共享ViewModel
class SharedViewModel : ViewModel() {private val _dataFromService = MutableLiveData<String>()val dataFromService: LiveData<String> = _dataFromServiceprivate val _serviceStatus = MutableLiveData<Boolean>()val serviceStatus: LiveData<Boolean> = _serviceStatusfun updateDataFromService(data: String) {_dataFromService.value = data}fun updateDataAsync(data: String) {_dataFromService.postValue(data)}fun updateServiceStatus(isRunning: Boolean) {_serviceStatus.value = isRunning}fun clearData() {_dataFromService.value = null_serviceStatus.value = false}override fun onCleared() {super.onCleared()Log.d("SharedViewModel", "ViewModel被清理")}
}
2. 创建ViewModelStoreOwner管理器
class SharedViewModelStoreOwner : ViewModelStoreOwner {private var viewModelStore: ViewModelStore? = ViewModelStore()override fun getViewModelStore(): ViewModelStore {return viewModelStore ?: ViewModelStore().also { viewModelStore = it }}fun clear() {Log.d("ViewModelManager", "清理SharedViewModel")viewModelStore?.clear()viewModelStore = null}fun recreate() {Log.d("ViewModelManager", "重建ViewModelStore")clear()viewModelStore = ViewModelStore()}fun isCleared(): Boolean = viewModelStore == null
}
3. 在Application中管理
class MyApplication : Application() {private val sharedViewModelStoreOwner = SharedViewModelStoreOwner()fun getSharedViewModel(): SharedViewModel {return ViewModelProvider(sharedViewModelStoreOwner).get(SharedViewModel::class.java)}fun clearSharedViewModels() {sharedViewModelStoreOwner.clear()}fun recreateSharedViewModels() {sharedViewModelStoreOwner.recreate()}fun isSharedViewModelsCleared(): Boolean = sharedViewModelStoreOwner.isCleared()override fun onLowMemory() {super.onLowMemory()Log.d("Application", "内存不足清理SharedViewModel")clearSharedViewModels()}override fun onTrimMemory(level: Int) {super.onTrimMemory(level)if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {Log.d("Application", "内存压力清理SharedViewModel")clearSharedViewModels()}}
}
4. Service中使用
class MyService : Service() {private val sharedViewModel: SharedViewModel by lazy {(application as MyApplication).getSharedViewModel()}override fun onCreate() {super.onCreate()Log.d("MyService", "Service启动")sharedViewModel.updateServiceStatus(true)startDataUpdate()}private fun startDataUpdate() {Handler(Looper.getMainLooper()).postDelayed(object : Runnable {override fun run() {val data = "Service数据: ${System.currentTimeMillis()}"sharedViewModel.updateDataAsync(data)Handler(Looper.getMainLooper()).postDelayed(this, 3000)}}, 3000)}fun sendDataToActivity(data: String) {sharedViewModel.updateDataFromService(data)}override fun onDestroy() {super.onDestroy()Log.d("MyService", "Service停止")sharedViewModel.updateServiceStatus(false)}
}
5. Activity 实现
class MainActivity : AppCompatActivity() {private val sharedViewModel: SharedViewModel by lazy {(application as MyApplication).getSharedViewModel()}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.d("MainActivity", "Activity创建")// 数据观察sharedViewModel.dataFromService.observe(this) { data ->data?.let {Log.d("MainActivity", "收到Service数据: $data")updateUI(data)}}// 服务状态观察sharedViewModel.serviceStatus.observe(this) { isRunning ->Log.d("MainActivity", "服务状态: ${if (isRunning) "运行中" else "已停止"}")updateServiceStatusUI(isRunning)}// 按钮事件绑定findViewById<Button>(R.id.btnStartService).setOnClickListener {startService(Intent(this, MyService::class.java))}findViewById<Button>(R.id.btnStopService).setOnClickListener {stopService(Intent(this, MyService::class.java))}findViewById<Button>(R.id.btnClearViewModel).setOnClickListener {clearSharedViewModel()}}private fun updateUI(data: String) {findViewById<TextView>(R.id.tvData).text = data}private fun updateServiceStatusUI(isRunning: Boolean) {findViewById<TextView>(R.id.tvServiceStatus).text = if (isRunning) "服务运行中" else "服务已停止"}private fun clearSharedViewModel() {Log.d("MainActivity", "手动清理SharedViewModel")(application as MyApplication).clearSharedViewModels()Toast.makeText(this, "SharedViewModel已清理", Toast.LENGTH_SHORT).show()}override fun onDestroy() {super.onDestroy()Log.d("MainActivity", "Activity销毁")}
}
6.布局文件
<!-- activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/tvServiceStatus"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="服务状态: 未启动"android:textSize="16sp"android:layout_marginBottom="16dp"/><TextViewandroid:id="@+id/tvData"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="等待数据..."android:textSize="14sp"android:layout_marginBottom="16dp"/><Buttonandroid:id="@+id/btnStartService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="启动Service"android:layout_marginBottom="8dp"/><Buttonandroid:id="@+id/btnStopService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="停止Service"android:layout_marginBottom="8dp"/><Buttonandroid:id="@+id/btnClearViewModel"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="清理SharedViewModel"android:layout_marginBottom="8dp"/>
</LinearLayout>
7.测试示例
class TestActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)testViewModelLifecycle()}private fun testViewModelLifecycle() {val app = application as MyApplication// 获取ViewModelval viewModel1 = app.getSharedViewModel()Log.d("Test", "第一次获取ViewModel: $viewModel1")// 验证实例复用val viewModel2 = app.getSharedViewModel()Log.d("Test", "第二次获取ViewModel: $viewModel2")Log.d("Test", "是否是同一个实例: ${viewModel1 === viewModel2}")// 清理测试app.clearSharedViewModels()Log.d("Test", "ViewModel是否已清理: ${app.isSharedViewModelsCleared()}")// 新实例验证val viewModel3 = app.getSharedViewModel()Log.d("Test", "清理后重新获取ViewModel: $viewModel3")Log.d("Test", "是否是新实例: ${viewModel1 !== viewModel3}")}
}
8. 完整的使用流程
使用流程总结:
// 1. Application创建SharedViewModelStoreOwner
// 2. Service通过Application获取SharedViewModel
// 3. Service调用updateDataFromService()发送数据
// 4. Activity观察LiveData接收数据
// 5. 使用完毕后调用clearSharedViewModels()手动清理
生命周期:
// Application.onCreate() → 创建SharedViewModelStoreOwner
// Service.onCreate() → 获取SharedViewModel,开始发送数据
// Activity.onCreate() → 获取SharedViewModel,开始观察数据
// 用户点击清理按钮 → 调用clearSharedViewModels()清理所有ViewModel
// Application.onLowMemory() → 自动清理(内存不足时)
总结
这个方案的特点:
- ✅ Application管理生命周期 - 统一管理SharedViewModel
- ✅ Service和Activity共享数据 - 通过LiveData实现响应式通信
- ✅ 手动回收机制 - 可以主动清理ViewModel
- ✅ 内存管理 - 内存不足时自动清理
- ✅ 生命周期安全 - 不会造成内存泄漏
使用场景:
- Service需要向多个Activity发送数据
- 需要持久化某些数据状态
- 需要在应用退出时主动清理资源
这样就能实现Service和UI的通信,并且能够完全控制ViewModel的生命周期!