Jetpack Compose中Datastore缓存Firebase图片:飞行模式缓存加载失败问题
修正Jetpack Compose中Datastore缓存Firebase图片的逻辑问题
问题分析
原代码存在三个核心问题:
- 判断条件先执行
firebaseImageUrl.toString()再判空,会触发空指针异常,当Firebase获取失败返回null时,直接崩溃进入catch块返回null,无法走到缓存逻辑 observeUserProfileImage中使用collect持续监听Datastore流,但Datastore的偏好设置流是永久活跃的,导致该函数永远不会返回值- 异常处理后直接返回null,没有 fallback 到Datastore缓存
修正后的代码
@HiltViewModel class ProfileViewModel @Inject constructor( // 注入依赖(dataStoreRepository、userRepository、auth等) ) : ViewModel() { private val _profilePicUrl = MutableStateFlow<String?>(null) val profilePicUrl: StateFlow<String?> = _profilePicUrl init { viewModelScope.launch { loadProfileImage() } } private suspend fun loadProfileImage() { // 先尝试从Firebase获取最新图片 val firebaseImageUrl = try { getUserData("profileImage") } catch (e: Exception) { Log.d("MelonFeedError", "Firebase获取失败: ${e.message}") null } // 处理Firebase返回的结果 val validFirebaseUrl = if (firebaseImageUrl != null) { val urlStr = firebaseImageUrl.toString() if (urlStr.contains("profilePicture_${auth.currentUser!!.uid}")) { // 有效URL,存入Datastore saveData(urlStr) urlStr } else { null } } else { null } // 优先用Firebase的有效URL,否则用Datastore缓存 val displayUrl = validFirebaseUrl ?: getCachedImageUrl() _profilePicUrl.value = displayUrl } private suspend fun getCachedImageUrl(): String? { // 只取Datastore当前的缓存值,不用持续监听 return dataStoreRepository.getImageURL().firstOrNull() } private suspend fun getUserData(fieldName: String): Any? { return userRepository.getCurrentUserData(fieldName) } private fun saveData(imageURL: String) { viewModelScope.launch { dataStoreRepository.saveImageURL(imageURL) } } // 其他代码 }
关键改动说明
- 修复空指针:先判断
firebaseImageUrl != null,再执行toString()和包含性检查 - 简化缓存读取:用
firstOrNull()获取Datastore的当前缓存值,避免持续监听导致函数挂起不返回 - 调整逻辑流程:
- 尝试从Firebase获取,捕获所有异常(包括网络错误)
- 验证Firebase返回的URL有效性,有效则存入缓存并使用该URL
- 若Firebase获取失败或URL无效,直接读取Datastore缓存并显示
- 优化StateFlow初始化:将
_profilePicUrl初始值设为null,更符合空状态语义
内容的提问来源于stack exchange,提问作者user23223024
相关产品推荐
相关产品推荐

