1

我正在使用AutoValue来处理getter/setterParcelable.

我将对象的 JSON 值存储在SharedPreferences其中,然后在需要时检索它们。但是,当我尝试将存储为 String 的 JSON 数组转换为时,这会引发异常,SharedPreferences因为ArrayList<T>我使用AutoValue的是不允许Constructor直接使用的。

这是我得到的例外 -

java.lang.RuntimeException: Failed to invoke public org.yadavvi.tutorials.governor.data.Governor() with no args
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:111)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:206)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
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:879)
at com.google.gson.Gson.fromJson(Gson.java:844)
at com.google.gson.Gson.fromJson(Gson.java:793)
at org.yadavvi.tutorials.governor.data.source.local.GovernorLocalDataSource.getGovernors(GovernorLocalDataSource.java:60)
at org.yadavvi.tutorials.governor.data.source.local.GovernorLocalDataSourceTest.getGovernors_callsOnSuccessOfGetGovernorsCallback(GovernorLocalDataSourceTest.java:69)

....

Caused by: java.lang.InstantiationException: Can't instantiate abstract class org.yadavvi.tutorials.governor.data.Governor
at java.lang.reflect.Constructor.newInstance(Native Method)
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:108)
... 41 more

这是Model/AutoValue班级的样子 -

package org.yadavvi.tutorials.governor.data;


import com.google.auto.value.AutoValue;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;

/**
 * Immutable Governor created using AutoValue.
 */
@AutoValue
public abstract class Governor {

    public static Governor create(String name) {
        return new AutoValue_Governor(name);
    }

    @SerializedName("name")
    abstract String name();
}

这是我尝试将 JSON 数组字符串转换为的类的ArrayList<T>样子 -

package org.yadavvi.tutorials.governor.data.source.local;


import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.util.Log;

import org.yadavvi.tutorials.governor.data.Governor;
import org.yadavvi.tutorials.governor.data.source.GovernorDataSource;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class GovernorLocalDataSource implements GovernorDataSource {

    ....

    @Override
    public void getGovernors(@NonNull GetGovernorsCallback callback) {
        Gson gson = new GsonBuilder().create();
        List<Governor> governors;

        String governorsString = mSharedPreference.getString(GOVERNORS, "");
        Log.i(TAG, "governorsString: " + governorsString);
        if (governorsString.equalsIgnoreCase("")) {
            governors = populateGovernors();
            governorsString = gson.toJson(governors);
            mSharedPreference.edit().putString(GOVERNORS, governorsString).commit();
        } else {
            governors = gson.fromJson(governorsString, new TypeToken<ArrayList<Governor>>(){}.getType());
        }

        if (governors != null && governors.size() > 0) {
            callback.onSuccess(governors);
        } else {
            callback.onFailure();
        }
    }

    ....

}

在这一行抛出异常 -

governors = gson.fromJson(governorsString, new TypeToken<ArrayList<Governor>>(){}.getType());

编辑:AutoValue-Extensions我的项目中有一些Android

应用程序 build.gradle看起来像这样 -

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "org.yadavvi.tutorials.governor"
        minSdkVersion 21
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.2.5'
    testCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    androidTestCompile 'org.mockito:mockito-core:2.2.5'

    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.google.auto.value:auto-value:1.2'
    compile 'com.ryanharter.auto.value:auto-value-gson:0.4.3'
}
4

2 回答 2

1

我已经添加了一个自定义TypeAdapterFactoryGsonBuilder它似乎工作正常。

TypeAdapterFactory看起来像这样-

package org.yadavvi.tutorials.governor.data;

import com.google.gson.typeadapterfactory;
import com.ryanharter.auto.value.gson.gsontypeadapterfactory;

@GsonTypeAdapterFactory
public abstract class GovernorAdapterFactory implements TypeAdapterFactory {

    public static GovernorAdapterFactory create() {
        return new AutoValueGson_GovernorAdapterFactory();
    }

}

GovernorLocalDataSource像这样改变-

public class GovernorLocalDataSource implements GovernorDataSource {

    @Override
    public void getGovernors(@NonNull GetGovernorsCallback callback) {
       Gson gson = new GsonBuilder()
               .registerTypeAdapterFactory(GovernorAdapterFactory.create())
               .create();
       List<Governor> governors;

       String governorsString = mSharedPreference.getString(GOVERNORS, EMPTY_STRING);
       if (governorsString.isEmpty()) {
           governors = populateGovernors();
           governorsString = gson.toJson(governors);
           mSharedPreference.edit().putString(GOVERNORS, governorsString).commit();
       } else {
           Type type = new TypeToken<ArrayList<Governor>>() {}.getType();
           governors = gson.fromJson(governorsString, type);
       }

       if (governors != null && governors.size() > 0) {
           callback.onSuccess(governors);
       } else {
           callback.onFailure();
       }

    }

}

PS:如果有人能解释为什么会这样,那就太好了。

于 2016-10-19T15:48:29.760 回答
0

下面的链接可能会有所帮助,基本上您需要使用具体类而不是抽象类。

Gson 反序列化 json。java.lang.RuntimeException:无法调用没有参数的公共 com.derp.procedure.model.SkeletonElement()] 根本原因

于 2016-10-19T11:18:08.707 回答