Android 不同包下ViewModel如何使用mBagOfTags自动关闭Closeable对象
解决方案
针对你需要复用ViewModel内部mBagOfTags自动关闭Closeable对象的需求,有两种可落地的实现方式,优先推荐第一种官方公开API方案:
方案1:使用官方ViewModel KTX扩展(无兼容风险,首选)
Android官方已经在lifecycle-viewmodel-ktx扩展包中公开了对应能力,本质是利用KTX包属于androidx.lifecycle包的权限优势,封装了对包私有setTagIfAbsent方法的调用,完全合法合规,没有反射风险。
- 第一步:在build.gradle中添加依赖
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" // 可替换为你使用的lifecycle兼容版本 }
- 第二步:直接在ViewModel中调用API
Kotlin写法:
Java写法:class MyViewModel : ViewModel() { init { // 直接传入你的Closeable实现类对象即可 addCloseable(myCloseableObj) } }public class MyViewModel extends ViewModel { public MyViewModel() { // KTX扩展方法在Java侧以静态方法形式调用 ViewModelKt.addCloseable(this, myCloseableObj); } }
调用后无需任何额外操作,ViewModel销毁时内部会自动调用该Closeable对象的close()方法。
方案2:反射调用包私有方法(不推荐,仅做兜底参考)
如果不想引入KTX依赖,可以通过反射直接调用ViewModel的setTagIfAbsent方法,但是存在版本兼容风险,官方后续修改ViewModel源码时可能导致逻辑失效。
示例代码(Kotlin):
import androidx.lifecycle.ViewModel import java.io.Closeable import java.lang.reflect.Method fun ViewModel.addCloseableByReflection(closeable: Closeable) { runCatching { val setTagMethod = ViewModel::class.java.getDeclaredMethod( "setTagIfAbsent", String::class.java, Any::class.java ) setTagMethod.isAccessible = true // 自定义唯一key避免和内部逻辑冲突 val uniqueKey = "custom_closeable_${closeable.hashCode()}" setTagMethod.invoke(this, uniqueKey, closeable) }.onFailure { // 反射失败时建议走兜底逻辑:自己维护Closeable列表,重写onCleared手动关闭 it.printStackTrace() } }
内容的提问来源于stack exchange,提问作者Ali Elahi
相关产品推荐
相关产品推荐

