Java 导致UI冻结的toJson方法
我有一个对象的ArrayList,我正在将其保存到Activities onPause方法中的SharedReferences。当我尝试将其序列化为json时,我在日志中得到以下内容(这两条语句重复并重载logcat): 我在onCreate中初始化ArrayList,然后在执行完异步任务后将对象赋给它。以下是导致UI冻结的问题方法:Java 导致UI冻结的toJson方法,java,android,gson,Java,Android,Gson,我有一个对象的ArrayList,我正在将其保存到Activities onPause方法中的SharedReferences。当我尝试将其序列化为json时,我在日志中得到以下内容(这两条语句重复并重载logcat): 我在onCreate中初始化ArrayList,然后在执行完异步任务后将对象赋给它。以下是导致UI冻结的问题方法: @Override protected void onPause() { super.onPause(); String json = mGso
@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();
jsonement元素=
mGson.toJsonTree(mSelectedContactList,newtypetoken()){
}.getType());
字符串jsonString=element.getAsJsonArray().getAsString();
我知道问题不在于共享引用。我怀疑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;
...
}
公共类ContactObject实现可包裹{
//实例变量
私有字符串mID;
私有字符串mNumber;
私有字符串mName;
私有布尔mHasPhoto;
私有ArrayMap mSentMessages;
私有阵列映射接收的消息;
...
}
我也有类似的问题。我几乎可以保证,问题是由于GSON很难序列化InboxSmsObject或OutboxSmsObject对象。ContactObject类看起来很简单,但您必须记住,GSON还必须序列化ArrayMap中的对象
您应该做的第一件事是尝试将ContactObject类中的一个或两个类更改为类似String的简单类。我敢打赌序列化在这种情况下是有效的
一旦确认确实如此,就可以着手解决问题。我采用的解决方案是创建一个简单的类,其中只包含构造InboxSmsObject所需的设置。例如,创建一个名为InboxSmsObjectSettings的类,该类只包含实例化InboxSmsObject类所需的基本信息(我想这个类只需要几个字符串)。然后创建一个构造函数,如
InboxSmsObject(InboxSmsObjectSettings设置)
因此,您可以从设置中轻松实例化InboxSmsObject。我知道这不是最好的解决方案,因为你需要重新编码一些东西,但它对我很有效 这可能是一个递归问题 请检查是否有递归模型,例如:
public class ClassA {
ClassB b;
}
public class ClassB {
List<ClassA> aList;
}
公共类ClassA{
b类;
}
公共B类{
清单主义者;
}
问题的一个可能原因是对类型标记的保护,可能是在混淆未被抑制的情况下。我也有一个非常类似的问题,总体情况是:
- 有一个简单的外部包可见类,只包含
实例,因此它是一个类型令牌注册表,以便在每次需要反序列化时不实例化类型令牌。值得注意的是(但实际上并不影响案例),类型标记被公开为包可见的静态最终字段TypeToken
- 有一个反序列化程序引用了注册表。一旦执行第一次反序列化(从而引用type tokens注册表类),应用程序UI线程将冻结,直到设备请求冻结应用程序并请求停止它
TypeToken
类中的某个构造函数导致挂起。这就是为什么仅仅一个简单的访问静态字段就会导致应用程序冻结的原因。我真的不记得是哪个构造函数导致了它,但我要声明,如果您的类型令牌参数化在ProGuard期间被擦除,那么GSON类型令牌可能会在其内部的某个地方运行到一个无限循环中。因此,只需重新配置ProGuard即可解决此问题:
-keepattributes Signature
有关详细信息,请参阅。如果您有ContactObject的构造函数,请删除它。之后应该可以正常工作。要序列化的JSON大小是多少?尝试使用只有一个元素的联系人列表,看看它是否仍然被卡住。我正在序列化对象的ArrayList。我查了一下尺寸,只有7号。我试试你的建议,只添加一个。数组列表中的对象是什么类型的?你不可能使用泛型,对吧?只是用列表中的一个对象尝试了一下,结果还是冻结了。这是一个自定义的可包裹对象。它是否“冻结”为应用程序内不再响应(ANR)?或者只是停一会儿?这不仅取决于物体的大小,还取决于物体的复杂程度。我不同意尤金的看法。如果他试图在活动关闭时执行某些操作,那么他应该在主线程上执行。如果在主线程之外执行,则不能保证在清理新线程之前完成序列化。我试着按照你的建议去做,并且多次看到Android过早地杀死了我的序列化线程。例如,如果用户从“最近的应用程序”列表中滑动进程,就会发生这种情况。确保序列化发生的唯一方法是使任务尽可能小,这就是为什么我们不只是像我们喜欢的那样生成线程,而是使用Android特定的工具,例如a)独立于活动b)在工作线程上执行。如果您收到Jose收到的错误,并且由于用户从最近的应用列表中刷取了应用而暂停了活动(这将最终终止进程),那么不管您是在线程、异步任务、前台服务还是服务内的工作线程中运行代码……Android将在它完成之前终止它,您将继续看到这些错误。服务和活动都位于同一进程上(除非您修改清单),s
-keepattributes Signature