java - 致命异常 : java. lang.RuntimeException - 由 java.lang.IllegalStateException 引起。应为 BEGIN_ARRAY,但实际为 BEGIN_OBJECT

标签 java android gson retrofit2 laravel-api

我在 Android 预发布报告中收到有关崩溃的报告。在我的模拟器和我拥有的三个物理测试设备上一切正常。报错如下

致命异常:java.lang.RuntimeException

执行 doInBackground() 时发生错误

android.os.AsyncTask$3.done (AsyncTask.java:353)
java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:383)
java.util.concurrent.FutureTask.setException (FutureTask.java:252)
java.util.concurrent.FutureTask.run (FutureTask.java:271)
android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:245)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1162)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:636)
java.lang.Thread.run (Thread.java:764)

由java.lang.IllegalStateException引起

预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT

com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read (CollectionTypeAdapterFactory.java)
retrofit2.converter.gson.GsonResponseBodyConverter.convert (GsonResponseBodyConverter.java:1)
retrofit2.OkHttpCall.a (OkHttpCall.java:59)
retrofit2.OkHttpCall.execute (OkHttpCall.java:73)
retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.execute (DefaultCallAdapterFactory.java:2)
com.cn.managers.CNServiceManager.fetchChapters (CNServiceManager.java:2)
com.cn.tasks.FetchChaptersTask.doInBackground (FetchChaptersTask.java:2)
com.cn.tasks.FetchChaptersTask.doInBackground (FetchChaptersTask.java:2)

FetchChaptersTask类中的doInBackground方法如下

@Override
protected ArrayList<Chapter> doInBackground(Void... voids) {
    return CNServiceManager.fetchChapters(subjectId, purpose);
}

在 CNServiceManager 中定义了方法 fetchChapters (subjectId, Purpose)。该方法基本上是使用 Retrofit2 和 GSON Converter 从 API 获取章节列表。 API调用如下。 CNServiceManager类如下:

public class CNServiceManager {

    public static final String PREF_AUTHENTICATION_TOKEN    = "CNServiceManager_authentication_token";
    public static final String PREF_SESSION_ID              = "CNServiceManager_session_id";

    private interface CNService {

        @GET("v2/chapters/{subjectId}/{purpose}")
        Call<ArrayList<Chapter>> fetchChapters(@Header("Authentication-Token") String authentication,
                                               @Path("subjectId") long subjectId,
                                               @Path("purpose") String purpose);
    }

    /**
     * Authorization token
     */
    private static String mAuthorizationToken;

    /**
     * The main interface to server
     */
    private static CNService mCNService;

    /**
     * Initialize
     *
     * @param context
     */
    public static void init(Context context) {

        OkHttpClient httpClient = new OkHttpClient.Builder()
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.0.105:8000/api/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient)
                .build();

        long applicationId = 9;
        String applicationSecret = "AppSecret";
        mAuthorizationToken = String.format(Locale.ENGLISH, "%d/%s", applicationId, applicationSecret);

        mCNService = retrofit.create(CNService.class);
    }

    /**
     * Returns authorization code
     *
     * @return
     */
    private static String getAuthorizationToken() {
        return mAuthorizationToken;
    }

    /**
     * Returns authentication code
     *
     * @return
     */
    private static String getAuthenticationToken() {
        return PreferencesManager.getString(PREF_AUTHENTICATION_TOKEN, null);
    }

    /**
     * Returns chapters
     *
     * @param subjectId
     * @param purpose
     * @return
     */
    public static ArrayList<Chapter> fetchChapters(long subjectId, String purpose) {
        try {
            Call<ArrayList<Chapter>> call = mCNService.fetchChapters(getAuthenticationToken(), subjectId, purpose);
            Response<ArrayList<Chapter>> response = call.execute();
            return response.body();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

最后,这是章节模型的编码方式。

public class Chapter {

    /**
     * Id of the chapter
     */
    private long id;

    /**
     * Name of the chapter
     */
    private String name;

    /**
     * Chapter
     *
     * @param id
     * @param name
     */
    public Chapter(long id, String name) {
        this.id = id;
        this.name = name;
    }

    /**
     * Chapter
     */
    public Chapter() {
        this(0, null);
    }

    /**
     * Returns the id of the chapter
     *
     * @return
     */
    public long getId() {
        return id;
    }

    /**
     * Sets the id of the chapter
     *
     * @param id
     */
    public void setId(long id) {
        this.id = id;
    }

    /**
     * Returns the name of the chapter
     *
     * @return
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the name of the chapter
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }
}

正如我在开头提到的,我在 Google Play 发布前报告和一些实时用户中收到了崩溃报告。但在我的设备和模拟器上,它没有崩溃。

最佳答案

请不要使用 AsyncTask 进行 Retrofit。相反,您可以使用 Reterofit 回调,如下所示。

public static void init(Context context) {

    OkHttpClient httpClient = new OkHttpClient.Builder()
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://192.168.0.105:8000/api/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient)
            .build();

    long applicationId = 9;
    String applicationSecret = "AppSecret";
    mAuthorizationToken = String.format(Locale.ENGLISH, "%d/%s", applicationId, applicationSecret);

    mCNService = retrofit.create(CNService.class);

    // additional code instead of AsyncTask
    Call<List<Chapter>> call = mCNService.fetchChapters();
    call.enqueue(new Callback<List<Chapter>>() {
        @Override
        public void onResponse(Call<List<Chapter>> call, Response<List<Chapter>> response) {
            progressDoalog.dismiss();
            generateDataList(response.body());
        }

        @Override
        public void onFailure(Call<List<Chapter>> call, Throwable t) {
            progressDoalog.dismiss();
            Toast.makeText(MainActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
        }
    });
}

希望这能解决您的问题

关于java - 致命异常 : java. lang.RuntimeException - 由 java.lang.IllegalStateException 引起。应为 BEGIN_ARRAY,但实际为 BEGIN_OBJECT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61431552/

相关文章:

java - 使用gson库将Json反序列化为java类

java - 部分 GSON 反序列化

java - "chmod"来自 Java 的 hadoop 路径

java - 为什么 SwingWorker 会意外停止?

java - java的正则表达式

android - Google Glass 应用更改时间线名称

android - 如何将数据库从我的 android 拉到我的桌面上?

android - 在 Android 中解析 JSON 对象

java - 如何将 GSON 的自定义可序列化方法转换为通用方法

java - 从 BigQuery 结果中获取 TableSchema PCollection<TableRow>