当前位置: 首页 > news >正文

实现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() → 自动清理(内存不足时)

总结

这个方案的特点

  1. ✅ Application管理生命周期 - 统一管理SharedViewModel
  2. ✅ Service和Activity共享数据 - 通过LiveData实现响应式通信
  3. ✅ 手动回收机制 - 可以主动清理ViewModel
  4. ✅ 内存管理 - 内存不足时自动清理
  5. ✅ 生命周期安全 - 不会造成内存泄漏

使用场景

  • Service需要向多个Activity发送数据
  • 需要持久化某些数据状态
  • 需要在应用退出时主动清理资源

这样就能实现Service和UI的通信,并且能够完全控制ViewModel的生命周期!

http://www.dtcms.com/a/276140.html

相关文章:

  • 卫星通信终端天线的5种对星模式之二:DVB跟踪
  • C++类模板继承部分知识及测试代码
  • Final
  • 剑指offer——树:二叉树的深度
  • 【C++小白逆袭】内存管理从崩溃到精通的秘籍
  • JVM 中“对象存活判定方法”全面解析
  • JVM的垃圾回收算法和多种GC算法
  • Git 相关的常见面试题及参考答案
  • 人工智能安全基础复习用:可解释性
  • 通过渐进蒸馏实现扩散模型的快速采样
  • Java-线程池
  • 【机器学习实战笔记 16】集成学习:LightGBM算法
  • AV1高层语法
  • PostgreSQL HOT (Heap Only Tuple) 更新机制详解
  • Swin Transformer核心思路讲解(个人总结)
  • 文件上传漏洞2-常规厂商检测限制绕过原理讲解
  • 强化学习、PPO和GRPO的通俗讲解
  • C语言第一章数据类型和变量(下)
  • Java 大视界:基于 Java 的大数据可视化在智慧城市能源消耗动态监测与优化决策中的应用(2025 实战全景)
  • 视频分析应用的搭建
  • 【Linux-云原生-笔记】Apache相关
  • NE综合实验2:RIP与OSPF动态路由优化配置、FTP/TELNET服务部署及精细化访问控制
  • Java反射与注解
  • 树形动态规划详解
  • 大数据时代UI前端的智能化服务升级:基于用户情境的主动服务设计
  • 【PycharmPyqt designer桌面程序设计】
  • 【学习新知识】用 Clang 提取函数体 + 构建代码知识库 + AI 问答系统
  • GD32 CAN1和TIMER0同时开启问题
  • 《通信原理》学习笔记——第一章
  • 细谈kotlin中缀表达式