Gson 未在生产模式 APK Android 中映射数据

Muh*_*ooq 7 android json gson

我正在使用 Gson 将数据映射到 ArrayList。在设备上或在调试模式下运行应用程序时它工作正常,但它没有在生产模式 APK 中映射数据。这是代码

Const.courses = new ArrayList<>();
    Log.v("Courses",object.toString());
    Type type = new TypeToken<ArrayList<Course>>() {
    }.getType();

    if(object != null && object.has("data") ){

        try {
            if(object.get("data") != null && object.getJSONArray("data").length()>0) {
                Const.courses.clear();
                Const.courses = new GsonBuilder().create().fromJson(object.getJSONArray("data").toString(), type);

                Log.d("Course from Array",Const.courses.get(0).getTitle());

  adapter = new CourseAdapter(getApplicationContext(), R.layout.course_row_layout, Const.courses);
                listView.setDivider(new ColorDrawable(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent)));
                listView.setAdapter(adapter);
            }else{
                tvSelectCourse.setVisibility(View.GONE);
                tvNoCourse.setVisibility(View.VISIBLE);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是 Logcat。任何帮助将不胜感激。

    02-16 23:30:57.836 1234-1234/? V/Courses: {"contentEncoding":null,"contentType":null,"data":[{"id":1,"title":"course Updated"},{"id":12,"title":"Arabic"},{"id":13,"title":"usman"},{"id":14,"title":"really "},{"id":15,"title":"urdu"},{"id":17,"title":"abc"},{"id":21,"title":"course"},{"id":22,"title":"Ali don"},{"id":24,"title":"umair"},{"id":25,"title":"math"},{"id":27,"title":"world"},{"id":28,"title":"wether"},{"id":33,"title":"computer Science "},{"id":34,"title":"cs"},{"id":37,"title":"maths"},{"id":38,"title":"hello"},{"id":39,"title":"course Updated"},{"id":42,"title":"for testing purpose"}],"jsonRequestBehavior":0,"maxJsonLength":null,"recursionLimit":null}
02-16 23:30:57.852 1234-1234/? D/AndroidRuntime: Shutting down VM
02-16 23:30:57.859 1234-1234/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: com.umer.doratiteacher, PID: 1234
                                                 java.lang.NullPointerException: println needs a message
                                                     at android.util.Log.println_native(Native Method)
                                                     at android.util.Log.d(Log.java:139)
                                                     at com.umer.doratiteacher.MainActivity$3.a(Unknown Source)
                                                     at com.umer.doratiteacher.d.a$3.a(Unknown Source)
                                                     at com.umer.doratiteacher.d.a$3.a(Unknown Source)
                                                     at com.a.a.a.i.a(Unknown Source)
                                                     at com.a.a.e$a.run(Unknown Source)
                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                     at android.os.Looper.loop(Looper.java:234)
                                                     at android.app.ActivityThread.main(ActivityThread.java:5526)
                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Run Code Online (Sandbox Code Playgroud)

Gar*_*y99 12

如前所述,问题出自 Proguard (when minifyEnabledtrue)。Proguard 摆脱了TypeGSON 需要解析的内容。

基于此链接https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg,我只需添加 3 行即可使我的代码正常工作

# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.example.YourPackage.** { *; }
Run Code Online (Sandbox Code Playgroud)

最后一行是您的代码所在的包的名称。如果您的所有代码都在一个主包中(一个目录中的所有 java 文件)或仅在一个文件中进行 GSON 解析,则将最后一行替换为(我已经测试了以上但没有测试以下)

-keep class com.example.YourPackage.YourClass.** { *; }
Run Code Online (Sandbox Code Playgroud)


Aal*_*lap 5

@Gary 正确地确定了 Proguard 是这里的问题。他给出的解决方案确实有效。实现此目的的另一种方法是添加

@Keep 
Run Code Online (Sandbox Code Playgroud)

注释从androidx.annotation.Keep到 yourClass。


Sub*_*sed 0

乍一看堆栈跟踪,看起来您正在传递null给 Log 调用:

Log.d("Course from Array",Const.courses.get(0).getTitle());

一个快速修复方法是在将方法传递给日志方法之前检查以确保该getTitle()方法不存在。null所以,像Log.d("Course from Array", TextUtils.isEmpty(Const.courses.get(0).getTitle()) ? "" : Const.courses.get(0).getTitle());