android 如何在屏幕旋转之间保存复杂的类示例?

hgtggwj0  于 2023-04-28  发布在  Android
关注(0)|答案(3)|浏览(98)

我正在构建一个通过蓝牙连接到设备的Android应用程序。我已经构建了一个相当复杂的类BleManager,用于处理应用程序的所有蓝牙方面。我面临着一个问题:每当我旋转手机屏幕时,类在维护状态时会遇到一些麻烦。我不会讲太多细节,因为我基本上需要粘贴数百行代码。要点是,我没有找到真实的的方法来保存在线搜索时屏幕旋转时UI相关对象的状态。我找到的唯一方法是Parcelize,但是保存简单对象以外的东西是相当混乱的。
我通过将BleManager的示例保存到静态object来解决这个问题。这通常不是理想的:如果我的类有多个示例,我不能把它们都保存在同一个对象中。另外,我的类在构造函数中接受了一个Context示例,Kotlin会抛出一个警告,说这会导致内存泄漏。我已经通过向类的构造函数传递一个contextProvider来解决这个问题,该函数返回一个Context,而不是Context对象本身。
难道没有更好的方法来可靠地保存屏幕旋转之间的复杂对象的状态吗?在我看来,这是非常基本的事情,以至于如此复杂。

qcuzuvrc

qcuzuvrc1#

将其放入ViewModel中。这至少会在配置更改时保留它。但是,如果Activity被销毁以节省内存,然后重新创建,它将丢失状态。如果即使在这些条件下也需要保留状态,那么您将不得不做一些事情,例如将其转换为包裹。您可能需要查看KotlinParcelize插件,以使这项工作更容易(更自动化)。
你的contextProvider是一个黑客,它不能解决根泄漏问题。它只会欺骗linter无法警告你。传递一个Application而不是Context,并从Application获取Context。Application的Context不能被泄漏,因为它在你的进程的生命周期中存在。我知道你想摆脱在object中使用静态引用,但这仍然适用于任何解决方案,其中您的BleManager将比Activity更长寿。

9udxz4iz

9udxz4iz2#

您可以使用Android架构组件提供的ViewModel类。ViewModels专门用于存储和管理UI相关数据,其方式可以在屏幕旋转等配置更改中保持不变。您可以使用ViewModel来保存BleManager对象的引用,并根据需要从Activity或Fragment访问它。
这样,只要ActivityFragment没有被破坏,BleManager示例将在屏幕旋转时保留。
另外,对于BleManager,你最好使用Context#getApplicationContext来避免内存泄漏。这是一个单例,在Activity销毁后不会导致内存泄漏。

我不建议你使用Parcelable来保存屏幕旋转后重新创建的大对象,因为如果你的Bundle太大,你可能会得到TransactionTooLargeException

rks48beu

rks48beu3#

您可以通过使用Android Jetpack架构组件提供的ViewModel类来实现这一点。ViewModel是一个旨在以生命周期意识的方式存储和管理UI相关数据的类。它允许数据在配置更改(如屏幕旋转)中生存。
下面是一个如何使用ViewModel的示例
创建你想要保存的Model类,我们称之为MyDataClass
创建一个扩展ViewModel类的新类。

import androidx.lifecycle.ViewModel

class MyViewModel : ViewModel() {
    var myDataClassInstance: MyDataClass? = null
}

在“活动”中,创建一个ViewModelProvider并检索MyViewModel的示例。

import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider

class MyActivity : AppCompatActivity() {
    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)

        // Get the instance of MyDataClass from the ViewModel
        var myDataClassInstance = myViewModel.myDataClassInstance

        // If the instance is null, create a new instance
        if (myDataClassInstance == null) {
            myDataClassInstance = MyDataClass()
            myViewModel.myDataClassInstance = myDataClassInstance
        }

        // Use myDataClassInstance in your Activity
    }
}

相关问题