我有一个服务器/客户端应用程序,我通过 Hessian/hessdroid 从服务器检索数据。数据非常复杂,HashMaps 包含其他 HashMaps 和存储在字节数组中的图像。我可以完美地显示数据。
为了不总是查询服务器,我使用数据结构作为缓存。我在关闭应用程序时使用 ObjectOutputStream 将此数据对象保存到 SD 卡。当我重新启动它时,我使用 ObjectInputStream 将其读回内存。
只有在从 SD 卡读取数据后,我才遇到应用程序问题。 LogCat 给我以下输出(100 次):
DEBUG/dalvikvm(4150): GetFieldID: unable to find field Ljava/util/HashMap;.loadFactor:F
这在其他消息之间:
INFO/dalvikvm-heap(4150): Grow heap (frag case) to 10.775MB for 281173-byte allocation
当堆增长到约 17 MB 时,应用程序崩溃。
我阅读了几个关于 HashMap 序列化的线程,在体系结构之间序列化时似乎存在错误,但对我来说,通过 Hessian 进行的数据传输工作得很好,我只有在从磁盘读取 HashMap 时才会遇到所描述的问题。
有什么想法吗?
最佳答案
正如 cyber-monk 评论的那样,该问题与 HashMap 反序列化没有直接关系。 Android 或它的 HashMap 实现中确实存在某种错误,但我认为这不是应用程序崩溃的原因。
现在我解决了这个问题,在应用程序中使用了更少的图像。例如,我有一个画廊,您可以在其中用脚蹼从一张图片滑动到下一张图片,然后一次加载所有图片。在一定数量的图像上,没有足够的堆空间。
我的解决方案是,不要一次保留所有解码图像。
它是这样完成的:
1) 将二进制图像数据保存在内存中(只要图像不是那么大就没有问题)
2) 在创建 flipper 的 View 时,不要将二进制图像数据加载到 ImageViews 中。
3) 将二进制图像数据设置到显示的ImageView中。
4) 保留下一个和上一个ImageView的二进制图像数据,更好的用户体验)
5) 通过将其资源设置为透明色来“卸载”未显示的ImageViews。
这是一些代码:
// initialize the viewFlipper by creating blank views
for (ComponentImageDto listElement : images) {
LinearLayout view = renderView();
flipper.addView(view);
}
showImage(flipper.getCurrentView());
renderView() 只返回一个包含 ImageView 的 LinearLayout
然后我写了一些方法来显示下一张/上一张图像,其中我将二进制数据设置为 ImageView:
private void showNextElement() {
// show next flipper view
flipper.showNext();
// get current view
int displayedChild = flipper.getDisplayedChild();
View currentView = flipper.getCurrentView();
// load the binary data
showImage(currentView);
// get the next to last view index (if keeping max. 3 images at a time in memory)
int otherChild = (displayedChild - 2);
if (otherChild < 0) {
otherChild = otherChild + flipper.getChildCount();
}
// .. and remove it
removeImage(flipper.getChildAt(otherChild));
}
private void showPreviousElement() {
flipper.showPrevious();
int displayedChild = flipper.getDisplayedChild();
View currentView = flipper.getCurrentView();
showImage(currentView);
setTitle((CharSequence) currentView.getTag());
int otherChild = (displayedChild + 2) % flipper.getChildCount();
removeImage(flipper.getChildAt(otherChild));
}
private void removeImage(View view) {
ImageView imageView = (ImageView) view.findViewById(R.id.gallery_image);
if (imageView != null) {
imageView.setImageResource(R.color.transparent);
System.gc();
}
}
private void showImage(View view) {
ImageView imageView = (ImageView) view.findViewById(R.id.gallery_image);
if (imageView != null) {
bm = BitmapHelper.decodeByteArray(images.get(flipper.getDisplayedChild()).getImage().getBinaryObject());
imageView.setImageBitmap(bm);
}
}
为了进一步改进内存处理,我使用了我在 stackoverflow 上找到的 BitmapHelper 类中的一些代码,这有助于通过减小图像的大小来节省图像的内存。
关于android - HashMap反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5471262/