Android开发:如何在屏幕旋转时保存复杂类实例状态?
解决屏幕旋转时复杂对象状态保留的可靠方案
针对你遇到的BleManager在屏幕旋转时状态丢失的问题,以下是几个比静态object更可靠的方案:
1. 使用ViewModel托管实例
ViewModel的核心特性就是跨越配置变化(如屏幕旋转)保留实例,完全适配你的场景:
- 创建一个继承自
AndroidViewModel的类,内部持有BleManager实例(使用Application Context避免内存泄漏):class BleViewModel(application: Application) : AndroidViewModel(application) { val bleManager = BleManager(application) } - 在Activity/Fragment中通过
ViewModelProvider获取ViewModel实例:
屏幕旋转时ViewModel不会被销毁,val viewModel = ViewModelProvider(this)[BleViewModel::class.java] // 直接使用viewModel.bleManager调用蓝牙逻辑BleManager的状态自然得以保留,同时彻底规避内存泄漏风险。
2. 使用依赖注入的Activity Retained作用域
如果项目使用Hilt或Dagger,可给BleManager设置ActivityRetained作用域:
- 以Hilt为例,给
BleManager添加@ActivityRetainedScoped注解,并注入Application Context:@ActivityRetainedScoped class BleManager @Inject constructor( @ApplicationContext private val context: Context ) { // 蓝牙相关逻辑实现 } - 在Activity/Fragment中注入实例:
@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var bleManager: BleManager // 业务逻辑中直接使用bleManager }@ActivityRetainedScoped的实例会在Activity配置变化时保留,自动管理生命周期,既解决了静态object的多实例冲突问题,也避免了内存泄漏。
3. (过时但兼容老项目)保留无UI Fragment实例
若不想使用ViewModel,可创建无UIFragment并调用setRetainInstance(true)托管BleManager:
- 创建保留实例的Fragment:
class BleRetainFragment : Fragment() { lateinit var bleManager: BleManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) retainInstance = true bleManager = BleManager(requireContext().applicationContext) } } - 在Activity中添加并获取该Fragment实例:
该方案已被ViewModel取代,但适配未引入Jetpack的老项目。private lateinit var bleRetainFragment: BleRetainFragment override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) bleRetainFragment = supportFragmentManager.findFragmentByTag("BleRetain") as? BleRetainFragment ?: run { BleRetainFragment().also { supportFragmentManager.beginTransaction().add(it, "BleRetain").commit() } } // 使用bleRetainFragment.bleManager操作蓝牙 }
这些方案均能可靠保留BleManager状态,同时规避静态object的诸多弊端,适配屏幕旋转等配置变化场景。
内容的提问来源于stack exchange,提问作者ultrapoci
相关产品推荐
相关产品推荐

