首页 > 解决方案 > 使用 Datastore 防止内存泄漏的最佳做法是什么?

问题描述

我尝试使用数据存储首选项 alpha07 存储和获取数据,一切正常,我在数据存储中遇到了一些内存泄漏问题

使用 Datastore 防止内存泄漏的最佳做法是什么?

这是我的示例代码:

// Preferences DataStore
    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha07"
// Leakcanary find memory leak
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'

用户管理器.kt

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class UserManager(val dataStore: DataStore<Preferences>) {

    //Create some keys
    companion object {
        val USER_AGE_KEY = intPreferencesKey("USER_AGE")
        val USER_FIRST_NAME_KEY = stringPreferencesKey("USER_FIRST_NAME")
        val USER_LAST_NAME_KEY = stringPreferencesKey("USER_LAST_NAME")
        val USER_GENDER_KEY = booleanPreferencesKey("USER_GENDER")
    }

    //Store user data
    suspend fun storeUser(age: Int, fname: String, lname: String, isMale: Boolean) {
        dataStore.edit {
            it[USER_AGE_KEY] = age
            it[USER_FIRST_NAME_KEY] = fname
            it[USER_LAST_NAME_KEY] = lname
            it[USER_GENDER_KEY] = isMale

        }
    }

    //Create an age flow
    val userAgeFlow: Flow<Int?> = dataStore.data.map {
        it[USER_AGE_KEY]
    }

    //Create a fname flow
    val userFirstNameFlow: Flow<String?> = dataStore.data.map {
        it[USER_FIRST_NAME_KEY]
    }

    //Create a lname flow
    val userLastNameFlow: Flow<String?> = dataStore.data.map {
        it[USER_LAST_NAME_KEY]
    }

    //Create a gender flow
    val userGenderFlow: Flow<Boolean?> = dataStore.data.map {
        it[USER_GENDER_KEY]
    }

}

用户.kt

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore

// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")

SignInFragment.kt

 //Get reference to our userManager class
               var userManager = UserManager(requireContext().dataStore)
        
                //Stores the values
                lifecycleScope.launch {
                    userManager.storeUser(1, "android", "studio", true)
                }

HomeFragment.kt

var userManager = UserManager(requireContext().dataStore)
       userManager.userAgeFlow.asLiveData().observe(requireActivity(), {
            if (it != null) {
                age = it
                //tv_age.text = it.toString()
            }
        })

内存泄漏问题: 在此处输入图像描述

在此处输入图像描述

我尝试了以下解决方案不起作用 ,即使尝试了此解决方案,我仍然会泄漏,在这种情况下,观察者应该与组件的生命周期绑定 Fragment 的生命周期。改用 viewLifeCycleOwner 来绑定观察者。

HomeFragment.kt

 var userManager = UserManager(viewLifecycleOwner.dataStore)
           userManager.userAgeFlow.asLiveData().observe(viewLifeCycleOwner, {
                if (it != null) {
                    // age = it
                    // tv_age.text = it.toString()
                }
            })

参考截图(再次复制) 在此处输入图像描述

标签: androidkotlinkotlin-coroutinesandroid-jetpackandroid-jetpack-datastore

解决方案


建议的修复

使用您的Activity'sorFragment's上下文确实很可疑,实际上没有必要这样做。applicationContext相反,如果您传递应用程序的全局上下文DataStorePreferences

在您的Fragments中,写下以下内容:

...
var userManager = UserManager(requireContext().applicationContext.dataStore) 
...

在你的MainActivity,它会更简单:

...
var userManager = UserManager(applicationContext.dataStore) 
...

结果

这就是检测到的泄漏数量:

在此处输入图像描述


推荐阅读