我正在尝试将 mutableList 保存到 mediaStore 中,但是我收到此错误:
java.lang.IllegalArgumentException: Type not supported: interface java.util.List
at com.alclabs.waltv.MainActivity.saveOnDataStore(MainActivity.kt:133)
at com.alclabs.waltv.MainActivity.access$saveOnDataStore(MainActivity.kt:20)
at com.alclabs.waltv.MainActivity$saveChannelsLocalStorage$1.invokeSuspend(MainActivity.kt:90)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8893)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@7c5ee8a, Dispatchers.Main.immediate]
这是我在 MainActivity 中的代码:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var dataStore: DataStore<Preferences>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
dataStore = createDataStore(name = "settings")
CoroutineScope(Dispatchers.IO).launch {
var state = loadChannels("https://anonymousfre.github.io/tv.html")
withContext(Dispatchers.Main) {
binding.txtStatus.text = state
}
}
}
private fun loadChannels(url: String): String {
//connect to url
var document = Jsoup.connect(url).get()
var channelsList = mutableListOf<String>()
//get channels url
var elements = document.select("ul.channels li")
for (element in elements) {
val channel = element.text()
channelsList.add(channel)
}
//get logos
var imagesList = mutableListOf<String>()
var elements2 = document.select("ul.images li")
for (element in elements2) {
val image = element.text()
imagesList.add(image)
}
//create final list of channels
var tvChannelsList = mutableListOf<TvChannel>()
channelsList.forEachIndexed { index, element ->
var ch = TvChannel(channelsList.get(index), imagesList.get(index))
tvChannelsList.add(ch)
}
//print channels..
/*
for(e in tvChannelsList){
println(e.channel_url+ " - " + e.channel_logo)
}
*/
saveChannelsLocalStorage(tvChannelsList)
return "channels loaded!"
}
private fun saveChannelsLocalStorage(listOfChannels: MutableList<TvChannel>) {
lifecycleScope.launch {
saveOnDataStore("channels_list", listOfChannels)
}
}
private suspend fun saveOnDataStore(key: String, value: MutableList<TvChannel>) {
val immutableList: List<TvChannel> = value.toList()
val dataStoreKey = preferencesKey<List<TvChannel>>(key)
dataStore.edit { settings ->
settings[dataStoreKey] = immutableList
}
}
}
基本上,我创建两个可变列表,然后创建 TvChannel 类型的对象的最终可变列表:
@Parcelize
data class TvChannel(
val channel_url: String,
val channel_logo: String,
) : Parcelable
我使用的是mediaStore版本:1.0.0-alpha01
implementation("androidx.datastore:datastore-preferences:1.0.0-alpha01")
问题出在这个方法上:
private suspend fun saveOnDataStore(key: String, value: MutableList<TvChannel>) {
val immutableList: List<TvChannel> = value.toList()
val dataStoreKey = preferencesKey<List<TvChannel>>(key)
dataStore.edit { settings ->
settings[dataStoreKey] = immutableList
}
}
在这里,基本上我将 mutableList 转换为 immutableList,但这不起作用。
如果你想测试我的代码,这里是用于进行网页抓取的 Jsoup 库:
implementation("org.jsoup:jsoup:1.11.3")
看起来首选项的数据存储实现不支持
List
。我无法找到有关支持哪些数据类型的任何文档,但由于这应该是 SharedPreferences
的替代品,所以我查看了 SharedPreferences
支持哪些数据类型。基本上,Set<String>
仅支持单一原始类型(无数组)和SharedPreferences
。如果您想在数据存储中存储更复杂的数据,您应该使用 Protobuf 实现而不是首选项实现。