Android数据存储首选项不会在读取尝试失败时引发IOException

5uzkadbs  于 2023-05-12  发布在  Android
关注(0)|答案(1)|浏览(107)

我正在使用Jetpack Compose构建一个Android应用程序,我想制作一个存储在数据存储首选项中的PIN码。我为它创建了以下数据源:

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "mydocument")

val PIN_CODE_KEY = stringPreferencesKey("pin_code")

class PinCodeLocalDataSource @Inject constructor(
    @ApplicationContext private val context: Context
) {
    fun getPinCode(): Flow<List<Int>> {
        Log.d(TAG, "Pin code status collected")
        return context.dataStore.data.map { preferences ->
            Log.d(TAG, "Data store mapped")
            val pin: String = preferences[PIN_CODE_KEY] ?: ""
            val intPin: List<Int> = pin.toCharArray().map {
                it.digitToIntOrNull() ?: 0
            }
            intPin
        }.catch { e ->
            Log.e(TAG, "Caught an exception while reading pin: ${e.message}")
        }
    }

    suspend fun setPinCode(newCode: List<Int>) {
        context.dataStore.edit { mutablePreferences ->
            mutablePreferences[PIN_CODE_KEY] = newCode.joinToString("") {
                it.toString()
            }
        }
    }
}

当查看logcat并启动我的应用程序时,它只显示“Pin code status collected”,但没有错误或任何表明它捕获了错误的内容。在错误时,我想发出一个错误状态,但没有catch{}就不能这样做。我做错了什么?
我尝试在下游捕获异常,但也没有成功。这是我的存储库方法的代码,它使用流构建器首先发出加载状态,然后它将流中的每个下一个值Map为状态:

fun load(): Flow<Loader<List<Int>>> = flow {
        emit(Loader.Loading)
        dataSource.getPinCode().onEach {
            emit(Loader.Success(it))
        }.catch { e ->
            Log.d(TAG, "Loading pin code failed.")
            if(e is IOException)
                emit(Loader.Error)
            else
                throw e
        }
    }.flowOn(Dispatchers.IO)
7gcisfzg

7gcisfzg1#

这真的很愚蠢,但唯一错的是我如何收集流量。onEach{}不是终端操作符,因此,正如cactustictacs正确假设的那样,流的主体永远不会运行。数据存储返回一个空值,如果它还没有被写入,所以我只是检查。新的repository方法:

fun load(): Flow<Loader<List<Int>>> = flow {
        emit(Loader.Loading)
        emitAll(
            dataSource.getPinCode()
                .map {
                    if(it.isNotEmpty())
                        Loader.Success(it)
                    else
                        Loader.Error
                }
                .catch { e ->
                    Log.d(TAG, "Loading pin code failed.")
                    if (e is IOException)
                        emit(Loader.Error)
                    else
                        throw e
                }
        )
    }

在这里,我使用flow builder和emitAll连接两个流

相关问题