我正在构建一个通过蓝牙连接到设备的Android应用程序。我已经构建了一个相当复杂的类BleManager
,用于处理应用程序的所有蓝牙方面。我面临着一个问题:每当我旋转手机屏幕时,类在维护状态时会遇到一些麻烦。我不会讲太多细节,因为我基本上需要粘贴数百行代码。要点是,我没有找到真实的的方法来保存在线搜索时屏幕旋转时非UI相关对象的状态。我找到的唯一方法是Parcelize,但是保存简单对象以外的东西是相当混乱的。
我通过将BleManager
的示例保存到静态object
来解决这个问题。这通常不是理想的:如果我的类有多个示例,我不能把它们都保存在同一个对象中。另外,我的类在构造函数中接受了一个Context
示例,Kotlin会抛出一个警告,说这会导致内存泄漏。我已经通过向类的构造函数传递一个contextProvider
来解决这个问题,该函数返回一个Context
,而不是Context
对象本身。
难道没有更好的方法来可靠地保存屏幕旋转之间的复杂对象的状态吗?在我看来,这是非常基本的事情,以至于如此复杂。
3条答案
按热度按时间qcuzuvrc1#
将其放入ViewModel中。这至少会在配置更改时保留它。但是,如果Activity被销毁以节省内存,然后重新创建,它将丢失状态。如果即使在这些条件下也需要保留状态,那么您将不得不做一些事情,例如将其转换为包裹。您可能需要查看KotlinParcelize插件,以使这项工作更容易(更自动化)。
你的
contextProvider
是一个黑客,它不能解决根泄漏问题。它只会欺骗linter无法警告你。传递一个Application而不是Context,并从Application获取Context。Application的Context不能被泄漏,因为它在你的进程的生命周期中存在。我知道你想摆脱在object
中使用静态引用,但这仍然适用于任何解决方案,其中您的BleManager将比Activity更长寿。9udxz4iz2#
您可以使用Android架构组件提供的
ViewModel
类。ViewModels专门用于存储和管理UI相关数据,其方式可以在屏幕旋转等配置更改中保持不变。您可以使用ViewModel
来保存BleManager
对象的引用,并根据需要从Activity或Fragment访问它。这样,只要
Activity
或Fragment
没有被破坏,BleManager
示例将在屏幕旋转时保留。另外,对于
BleManager
,你最好使用Context#getApplicationContext
来避免内存泄漏。这是一个单例,在Activity销毁后不会导致内存泄漏。我不建议你使用Parcelable来保存屏幕旋转后重新创建的大对象,因为如果你的Bundle太大,你可能会得到
TransactionTooLargeException
。rks48beu3#
您可以通过使用Android Jetpack架构组件提供的
ViewModel
类来实现这一点。ViewModel
是一个旨在以生命周期意识的方式存储和管理UI相关数据的类。它允许数据在配置更改(如屏幕旋转)中生存。下面是一个如何使用
ViewModel
的示例创建你想要保存的Model类,我们称之为
MyDataClass
。创建一个扩展
ViewModel
类的新类。在“活动”中,创建一个
ViewModelProvider
并检索MyViewModel
的示例。