gson 如何从SharedPreference加载包含MutableList的数据类< Uri>?

5n0oy7gb  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(201)

我尝试使用SharedPreference,加载数据时出现错误。我认为问题是我的数据类包含MutableList,但我不知道如何处理它。

private lateinit var albumData:MutableList<Album>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    loadData()

    connectAdapter()

    btnAddAlbum.setOnClickListener {
        if(isStoragePermitted()) {
            openGallery()
        }
    }
}

fun saveData() {
    val sharedPreferences = getSharedPreferences("shared preferences", Context.MODE_PRIVATE)
    val editor = sharedPreferences.edit()
    val gson = GsonBuilder().create()
    val json = gson.toJson(albumData)
    editor.putString("Album data", json)
    editor.apply()
}

fun loadData() {
    val sharedPreferences = getSharedPreferences("shared preferences", Context.MODE_PRIVATE)
    val gson = GsonBuilder().create()
    val json = sharedPreferences.getString("Album data", null)
    var test = mutableListOf<Album>()
    if(json != null) {
        Log.d("Log_show", "data load 1")
        val type = object : TypeToken<MutableList<Album>>() {}.type
        Log.d("Log_show", "data load 2")
        albumData = gson.fromJson<MutableList<Album>>(json, type)
        Log.d("Log_show", "data load 3")
    }else{
        albumData =  mutableListOf()
    }
}

override fun onDestroy() {
    saveData()
    Log.d("Log_show", "shut down")
    super.onDestroy()
}

以上是我在主要活动中的部分职能。

data class Album (
    var albumImages : MutableList<Uri>,
    var albumTitle : String,
    var pictureCount : Int
)

这是我的数据类“Album”
当我第一次打开应用程序,它保存数据很好,没有错误发生。
但是当我关闭应用程序并再次打开它时,加载数据的过程中发生错误
这是我的日志的一部分“Log_show”和“data load 3”没有出现
2020-11-04 23:12:33.418 15720-15720/kr.公司. dodophi.自动更换壁纸D/log:数据加载1
2020-11-04 23:12:33.420 15720-15720/kr.公司. dodophi.自动更换壁纸D/log:数据加载器2
完整日志如下所示

2020-11-05 14:48:19.319 6956-6956/kr.co.ddophi.autochangingwallpaper D/Log_show: data load 1 2020-11-05 14:48:19.321 6956-6956/kr.co.ddophi.autochangingwallpaper D/Log_show: data load 2 2020-11-05 14:48:19.331 6956-6956/kr.co.ddophi.autochangingwallpaper D/AndroidRuntime: Shutting down VM 2020-11-05 14:48:19.336 6956-6956/kr.co.ddophi.autochangingwallpaper E/AndroidRuntime: FATAL EXCEPTION: main Process: kr.co.ddophi.autochangingwallpaper, PID: 6956 java.lang.RuntimeException: Unable to start activity ComponentInfo{kr.co.ddophi.autochangingwallpaper/kr.co.ddophi.autochangingwallpaper.MainActivity}: java.lang.RuntimeException: Failed to invoke private android.net.Uri() with no args at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032) at android.app.ActivityThread.-wrap11(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6944) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) Caused by: java.lang.RuntimeException: Failed to invoke private android.net.Uri() with no args at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at com.google.gson.Gson.fromJson(Gson.java:927) at com.google.gson.Gson.fromJson(Gson.java:892) at com.google.gson.Gson.fromJson(Gson.java:841) at kr.co.ddophi.autochangingwallpaper.MainActivity.loadData(MainActivity.kt:174) at kr.co.ddophi.autochangingwallpaper.MainActivity.onCreate(MainActivity.kt:43) at android.app.Activity.performCreate(Activity.java:7183) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)  at android.app.ActivityThread.-wrap11(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)  at android.os.Handler.dispatchMessage(Handler.java:105)  at android.os.Looper.loop(Looper.java:164)  at android.app.ActivityThread.main(ActivityThread.java:6944)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)  Caused by: java.lang.InstantiationException: Can't instantiate abstract class android.net.Uri at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:334) at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:110) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)  at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)  at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)  at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)  at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)  at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)  at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)  at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)  at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)  at com.google.gson.Gson.fromJson(Gson.java:927)  at com.google.gson.Gson.fromJson(Gson.java:892)  at com.google.gson.Gson.fromJson(Gson.java:841)  at kr.co.ddophi.autochangingwallpaper.MainActivity.loadData(MainActivity.kt:174)  at kr.co.ddophi.autochangingwallpaper.MainActivity.onCreate(MainActivity.kt:43)  at android.app.Activity.performCreate(Activity.java:7183)  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)  at android.app.ActivityThread.-wrap11(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)  at android.os.Handler.dispatchMessage(Handler.java:105)  at android.os.Looper.loop(Looper.java:164)  at android.app.ActivityThread.main(ActivityThread.java:6944)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) 

任何帮助都将不胜感激
谢谢你

4ktjp1zp

4ktjp1zp1#

应自定义TypeAdapter以序列化和反序列化URI。

class UriTypeAdapter : TypeAdapter<Uri>() {
    override fun write(out: JsonWriter?, value: Uri?) {
        value?.let {
            out?.value(it.toString())
        } ?: run {
            out?.nullValue()
        }
    }

    override fun read(reader: JsonReader?): Uri {
        return if (reader?.peek() == JsonToken.NULL) {
            reader.nextNull()
            Uri.EMPTY
        } else {
            val uriString = reader?.nextString()
            uriString?.let {
                Uri.parse(it)
            } ?: run {
                Uri.EMPTY
            }
        }
    }
}

然后像这样设置Gson:

val gson = GsonBuilder()
    .registerTypeHierarchyAdapter(Uri::class.java, UriTypeAdapter())
    .create()

相关问题