Android Jetpack DataStore插桩测试中获取Proto字符串列表抛NoClassDefFoundError
Android DataStore Proto Store插桩测试获取List报错排查
我在Android应用的公共模块中将SharedPreferences替换为DataStore,用DataProperty便捷访问参数,同时按需注入MyDataStore接口。因业务需求还实现了proto store,所有功能运行正常,迁移过程顺利,但运行插桩测试时,应用尝试从proto store获取List时抛出对应错误。
相关配置
build.gradle(:app) 配置
androidTestImplementation(libs.androidx.datastore.core) androidTestImplementation(libs.androidx.datastore.preferences) androidTestImplementation(libs.androidx.datastore.preferences.core) androidTestImplementation(project(":common")) testImplementation(project(":common")) androidTestImplementation(libs.protobuf.javalite) testImplementation(libs.protobuf.javalite)
版本统一配置
为确保protobuf-javalite版本一致,添加了如下配置:
allprojects { configurations.all { resolutionStrategy.eachDependency { if (requested.group == "com.google.protobuf" && requested.name == "protobuf-javalite") { useVersion("3.25.1") because("Older versions lack registerDefaultInstance()") } } } }
核心代码实现
StringListSerializer 定义
private class StringListSerializer : Serializer<List<String>> { override val defaultValue: List<String> get() = emptyList() override suspend fun readFrom(input: InputStream): List<String> { try { val longList = ListOfString.parseFrom(input) return longList.itemList } catch (exception: Exception) { throw CorruptionException("Cannot read proto.", exception) } } override suspend fun writeTo(t: List<String>, output: OutputStream) { val longList = ListOfString.newBuilder() .addAllItem(t) .build() longList.writeTo(output) } }
StringListDataStoreProperty 实现
class StringListDataStoreProperty( private val context: Context, private val dataStoreName: String, private val coroutineScope: CoroutineScope ) : ReadWriteProperty<Any, List<String>?> { private val Context.listOfLongDataStore: DataStore<List<String>> by dataStore( fileName = dataStoreName, serializer = StringListSerializer(), ) override fun getValue(thisRef: Any, property: KProperty<*>): List<String> = runBlocking { return@runBlocking context.listOfLongDataStore.data.first() } override fun setValue(thisRef: Any, property: KProperty<*>, value: List<String>?) { coroutineScope.launch { context.listOfLongDataStore.updateData { value!! } } } }
MyDataStoreManager 实现
class MyDataStoreManager @Inject constructor( @ApplicationContext val context: Context, @ApplicationScope val coroutineScope: CoroutineScope, private val dataStore: DataStore<Preferences> ) : MyDataStore { //... override var myListOfStrings: List<String>? by StringListDataStoreProperty( context = context, dataStoreName = "protoStoreName", coroutineScope = coroutineScope ) //... }
请问我遗漏了什么配置或者哪里操作有误?
内容的提问来源于stack exchange,提问作者ViksaaSkool
相关产品推荐
相关产品推荐

