getActivity / EasyHttp

Android 网络请求框架,简单易用,so easy
Apache License 2.0
1.4k stars 191 forks source link

[Bug]:读取缓存失败 #233

Closed traywangjun closed 8 months ago

traywangjun commented 8 months ago

框架版本【必填】

12.8

问题描述【必填】

在readCache里调用GsonFactory.getSingletonGson().fromJson(cacheValue, type)解析异常

复现步骤【必填】

image Api设置CacheMode,请求一次接口然后再次访问

是否必现【必填】

项目 targetSdkVersion【必填】

34

出现问题的手机信息【必填】

三星s21

出现问题的安卓版本【必填】

14

问题信息的来源渠道【必填】

自己遇到的

是部分机型还是所有机型都会出现【必答】

全部

框架最新的版本是否存在这个问题【必答】

框架文档是否提及了该问题【必答】

是否已经查阅框架文档但还未能解决的【必答】

issue 列表中是否有人曾提过类似的问题【必答】

是否已经搜索过了 issue 列表但还未能解决的【必答】

是否可以通过 Demo 来复现该问题【必答】

提供报错堆栈

Abstract classes can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Class
                                                                                                    name: [Ljava.lang.String;
                                                                                                    com.google.gson.JsonIOException: Abstract classes can't be instantiated! Register an InstanceCreator or a
                                                                                                    TypeAdapter for this type. Class name: [Ljava.lang.String;
                                                                                                        at com.hjq.gson.factory.constructor.ExceptionConstructor.construct(ExceptionConstructor.java:22)
                                                                                                        at
                                                                                                    com.hjq.gson.factory.constructor.KotlinDataClassDefaultValueConstructor.getTypeDefaultValue(KotlinDataClassDefaultValueConstructor.kt:91)
                                                                                                        at
                                                                                                    com.hjq.gson.factory.constructor.KotlinDataClassDefaultValueConstructor.construct(KotlinDataClassDefaultValueConstructor.kt:59)
                                                                                                        at
                                                                                                    com.hjq.gson.factory.constructor.ReflectSafeCreatorConstructor.construct(ReflectSafeCreatorConstructor.java:27)
                                                                                                        at com.hjq.gson.factory.element.ReflectiveTypeAdapter.read(ReflectiveTypeAdapter.java:57)
                                                                                                        at com.hjq.gson.factory.element.ReflectiveTypeUtils$1.read(ReflectiveTypeUtils.java:106)
                                                                                                        at com.hjq.gson.factory.element.ReflectiveTypeAdapter.read(ReflectiveTypeAdapter.java:70)
                                                                                                        at com.google.gson.Gson.fromJson(Gson.java:1227)
                                                                                                        at com.google.gson.Gson.fromJson(Gson.java:1137)
                                                                                                        at com.google.gson.Gson.fromJson(Gson.java:1047)
                                                                                                        at com.google.gson.Gson.fromJson(Gson.java:1014)
                                                                                                        at com.hjq.easy.demo.http.model.RequestHandler.readCache(RequestHandler.java:213)
                                                                                                        at com.hjq.http.callback.NormalCallback.start(NormalCallback.java:54)
                                                                                                        at com.hjq.http.request.HttpRequest.lambda$request$1$HttpRequest(HttpRequest.java:321)
                                                                                                        at com.hjq.http.request.-$$Lambda$HttpRequest$M_eqDBbouDNuYU3ARc3t5jTc22c.run(Unknown Source:6)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                                                                                        at java.lang.Thread.run(Thread.java:1012)

提供截图或视频

image

提供解决方案

No response

traywangjun commented 8 months ago

刚发现了 是okhttp版本的问题,我把demo里的okhttp改为4.11.0就会出现

getActivity commented 8 months ago

小伙子,我对这个问题进行了实践,确实存在这个问题,具体问题原因是 HttpData 定义了 Headers 类型的字段,即名为 responseHeaders 字段,因为 Gson 内部无法对这种类型进行序列化和反序列化,所以出现解析报错,旧版本之所以没有这个问题,是因为旧版本的 OkHttp 是用 Java 语言写的,而到了新版本,则是用 Kotlin 语言写的,解决这个问题的方法也很简单,将 responseHeaders 字段类型从 Headers 修改成 Map 类型,具体的代码改动如下:

public class HttpData<T> {

    /** 响应头 */
    @Nullable
    private Map<String, String> responseHeaders;

    public void setResponseHeaders(@Nullable Map<String, String> responseHeaders) {
        this.responseHeaders = responseHeaders;
    }

    @Nullable
    public Map<String, String> getResponseHeaders() {
        return responseHeaders;
    }
    ......
}
public final class RequestHandler implements IRequestHandler {

    ......

    @NonNull
    @Override
    public Object requestSuccess(@NonNull HttpRequest<?> httpRequest, @NonNull Response response, @NonNull Type type) throws Throwable {

        ......

        if (result instanceof HttpData) {
            HttpData<?> model = (HttpData<?>) result;
            Headers headers = response.headers();
            int headersSize = headers.size();
            Map<String, String> headersMap = new HashMap<>(headersSize);
            for (int i = 0; i < headersSize; i++) {
                headersMap.put(headers.name(i), headers.value(i));
            }
            model.setResponseHeaders(headersMap);

            ......
        }
        return result;
    }
}
traywangjun commented 8 months ago

验证了下确实可以了