toJson方法导致UI冻结

时间:2015-06-21 03:50:02

标签: java android gson

我有一个对象的ArrayList,我在Activities onPause方法中保存到SharedPreferences。当我尝试将它序列化为json时,我在日志中得到以下内容(这两个语句重复并重载logcat):

06-20 20:33:31.620  26245-26252/com.example.app W/art﹕ Suspending all threads took: 21.556ms
06-20 20:33:31.620  26245-26260/com.example.app W/art﹕ Suspending all threads took: 5.901ms
06-20 20:33:31.650  26245-26260/com.example.app I/art﹕ Background partial concurrent mark sweep GC freed 210493(6MB) AllocSpace objects, 87(2MB) LOS objects, 25% free, 47MB/63MB, paused 16.970ms total 155.761ms
06-20 20:33:32.480  26245-26260/com.example.app I/art﹕ Background sticky concurrent mark sweep GC freed 346396(10MB) AllocSpace objects, 140(4MB) LOS objects, 14% free, 48MB/56MB, paused 13ms total 88.199ms

我在onCreate中初始化ArrayList,然后在执行Asynctask时给它提供对象。以下是导致UI冻结的问题方法:

  @Override 
  protected void onPause() {
  super.onPause();
  String json = mGson.toJson(mSelectedContactList);
  mSharedPreferences.edit().putString("contact_list", json).apply();
  }

我也尝试了以下内容并继续冻结:

    JsonElement element =
    mGson.toJsonTree(mSelectedContactList, new TypeToken<ArrayList<ContactObject>>() {
    }.getType());
    String jsonString = element.getAsJsonArray().getAsString();

我知道问题不在于SharedPreferences。我怀疑toJson方法无法处理这个过程,但我无法弄清楚这里有什么问题。任何帮助都感激不尽。

*编辑:这是我正在使用的课程:

public class ContactObject implements Parcelable {

// Instance variables
private String mID;
private String mNumber;
private String mName;
private boolean mHasPhoto;
private ArrayMap<Long, InboxSmsObject> mSentMessages;
private ArrayMap<Long, OutboxSmsObject> mReceivedMessages;
...
}

4 个答案:

答案 0 :(得分:0)

我遇到过类似的问题。我几乎可以保证问题是由于GSON很难序列化您的InboxSmsObject或OutboxSmsObject对象。您的ContactObject类看起来很简单,但您必须记住,GSON还必须序列化ArrayMap中的对象。

您应该做的第一件事是尝试将ContactObject类中的一个或两个类更改为一些简单的类,如String。我敢打赌,序列化在这种情况下有效。

一旦确认确实如此,那么您就可以开始使用解决方案了。我使用的解决方案是创建一个简单的类,只需要构造InboxSmsObject所需的设置。例如,创建一个名为InboxSmsObjectSettings的类,它只包含实例化InboxSmsObject类所需的基本信息(我猜这个类只需要几个字符串)。然后创建一个像

这样的构造函数

InboxSmsObject(InboxSmsObjectSettings设置)

这样您就可以从设置中轻松实例化InboxSmsObject。我知道这不是最好的解决方案,因为你必须重新编码一些东西,但它对我有用。

答案 1 :(得分:0)

这可能是一个递归问题。

请检查您是否具有递归模型,例如:

public class ClassA {

   ClassB b;

}

public class ClassB {

   List<ClassA> aList;

}

答案 2 :(得分:0)

问题的一个可能原因是ProGuard-over over类型令牌,可能是在未抑制混淆时。我也有一个非常相似的问题,整体情况是:

  • 只有一个简单的外部包可见类,只包含TypeToken个实例,因此是一个类型标记注册表,以便每次我需要反序列化时不实例化类型标记。值得注意的是(但并未真正影响案例),类型标记作为包可见的静态最终字段公开。
  • 有一个引用注册表的反序列化器。一旦执行了第一个反序列化(因此引用类型令牌注册表类),应用程序UI线程就会冻结,直到设备要求冻结应用程序要求停止它。

我没有立即注意到静态字段初始化器是冻结的原因。经过一些调试后,我意识到抽象TypeToken类中的一些构造函数会导致挂起。这就是为什么只是一个简单的访问静态字段导致应用程序冻结。我真的不记得哪个构造函数导致它,但我会声称如果在ProGuarding期间擦除了类型标记参数化,GSON类型标记可能会在其内部某处遇到无限循环。因此,重新配置ProGuard可以解决问题:

-keepattributes Signature

查看ProGuard Attributes的详情。

答案 3 :(得分:0)

如果你有ContactObject的构造函数,只需删除它。之后它应该可以正常工作。