如何在Kotlin的Fragment中初始化Preference DataStore类以获取登录保存数据
在Fragment中初始化Preference DataStore并获取登录数据的正确实现方法
1. 先创建Preference DataStore全局管理类
推荐用单例模式封装DataStore,避免重复实例化,同时统一管理所有偏好键:
import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map // 扩展Context,创建全局DataStore实例 val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_preferences") class DataStoreManager(private val context: Context) { // 定义登录相关的偏好键 companion object { val USER_ID = stringPreferencesKey("user_id") val USER_NAME = stringPreferencesKey("user_name") val LOGIN_TOKEN = stringPreferencesKey("login_token") } // 获取用户ID的Flow val userIdFlow: Flow<String?> = context.dataStore.data .map { preferences -> preferences[USER_ID] } // 获取登录Token的Flow val loginTokenFlow: Flow<String?> = context.dataStore.data .map { preferences -> preferences[LOGIN_TOKEN] } // 保存登录信息 suspend fun saveLoginInfo(userId: String, userName: String, token: String) { context.dataStore.edit { preferences -> preferences[USER_ID] = userId preferences[USER_NAME] = userName preferences[LOGIN_TOKEN] = token } } // 清除登录信息(退出登录用) suspend fun clearLoginInfo() { context.dataStore.edit { preferences -> preferences.remove(USER_ID) preferences.remove(USER_NAME) preferences.remove(LOGIN_TOKEN) } } }
2. 在Fragment中初始化并使用DataStoreManager
直接通过requireContext()获取实例,建议在onViewCreated之后初始化,确保Context就绪:
class LoginFragment : Fragment() { private lateinit var dataStoreManager: DataStoreManager override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化DataStoreManager dataStoreManager = DataStoreManager(requireContext()) // 观察登录数据 observeLoginData() } private fun observeLoginData() { // 用viewLifecycleOwner的协程,绑定Fragment生命周期避免内存泄漏 viewLifecycleOwner.lifecycleScope.launchWhenStarted { // 收集用户ID数据 dataStoreManager.userIdFlow.collect { userId -> userId?.let { // 拿到用户ID后的UI逻辑 binding.tvUserId.text = "用户ID: $it" } ?: run { // 未登录状态处理 binding.tvUserId.text = "未登录" } } } viewLifecycleOwner.lifecycleScope.launchWhenStarted { // 收集登录Token dataStoreManager.loginTokenFlow.collect { token -> token?.let { // 用Token做接口请求等操作 } } } } }
核心注意事项
- 必须通过协程收集DataStore的
Flow,因为DataStore是异步操作,不支持同步获取数据 - 优先使用
viewLifecycleOwner.lifecycleScope或launchWhenStarted,确保Fragment销毁时自动取消协程 - 避免在
onCreate/onCreateView阶段调用requireContext(),尽量在视图创建完成后初始化
内容的提问来源于stack exchange,提问作者Pragyanshree Das
相关产品推荐
相关产品推荐

