Litepal的那些坑
Activity/Fragment 之间传递对象引发的问题
在 Activity/Fragment 之间传递参数,包括对象,已经是司空见惯的基本技能了。但是牵涉到 Litepal 的时候就会有些困难了……
情形如下:
有一个列表页 Activity
L(List),之中持有多个模型对象,当我准备开发一个详情页时,将模型对象定义为 Serializable
,然后通过以下方式传给详情页的 Fragment
:
Bundle bundle = new Bundle(); bundle.putSerializable("object", object); fragment.setArguments(bundle);
OK,没有问题,对象的属性已经顺利地传给了 Fragment
了(抛去级联对象这个问题)。
但是接下来,我要在详情页中实现一个删除这个对象的功能,由于模型对象已经继承了 Litepal 的 DataSupport
,理所当然的:
object.delete();
好像并没有删除成功,方法返回了 false。
调试后发现在传递过程中对象发生了改变,DataSupport
中的 baseObjId
被修改为了 0。从而引发 isSaved()
方法返回 false。因为 isSaved()
返回了 false,接下来 delete()
方法什么也不做:
// DataSupport.java public boolean isSaved() { return baseObjId > 0; } // DeleteHandler.java int onDelete(DataSupport baseObj) { if (baseObj.isSaved()) { List<Field> supportedGenericFields = getSupportedGenericFields(baseObj.getClassName()); deleteGenericData(baseObj.getClass(), supportedGenericFields, baseObj.getBaseObjId()); Collection<AssociationsInfo> associationInfos = analyzeAssociations(baseObj); int rowsAffected = deleteCascade(baseObj); rowsAffected += mDatabase.delete(baseObj.getTableName(), "id = " + baseObj.getBaseObjId(), null); clearAssociatedModelSaveState(baseObj, associationInfos); return rowsAffected; } return 0; }
更进一步地发现,DataSupport
并没有实现 Serializable
,因此其中的属性并没有被序列化。
解决办法有好一些:
- 使用
DataSupport.delete
,通过指定 ID 的方式删除 - 不把对数据操作放在被传递的组件中
- 在被传递的组件中,根据对象的 ID,重新获取一次对象
- 被传递的组件只反映动作,通过返回码由上一级组件实际执行动作
本文采用 CC BY-NC-SA 3.0 协议进行许可,在您遵循此协议的情况下,可以自由共享与演绎本文章。
本文链接:https://blog.codeingboy.me/questions-about-litepal/