首先,我理解有关java.lang.OutOfMemoryError
和Bitmaps的问题之前已经被多次询问过。我还查看了Displaying Bitmaps Efficiently页面。
我的用例:
我在SQLite数据库中将两个不同大小的位图存储为字符串。位图的第一个尺寸是屏幕宽度的50%,第二个尺寸是屏幕宽度的100%。
我正在使用RecyclerView在ImageViews中显示图像,这些图像是屏幕宽度的50%或100%,因此加载的位图并不比它们需要的大,并且它们之前的大小合适从数据库中检索图像。
我也在使用AsyncTask加载位图。
我在RecyclerView中有12个不同的项目,所以我通过以下代码创建了总共24个位图(2个大小的12个图像):BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
问题
活动在没有java.lang.OutOfMemoryError
的情况下加载,除非我连续5次重新启动相同的Activity(例如加载Activity,然后通过在导航抽屉中再次单击它重新创建活动,然后重复该过程)。
可能的解决方案
如果我在onPause生命周期事件中回收位图,如下所示:
public void recycleBitmaps(){
int howManyBitmaps = bitmapsFullScreenWidth.size();
for (int i = 0; i < howManyBitmaps; i++) {
if (recyclerAdapter.bitmapsHalfScreenWidthArrayList.get(i) != null && !recyclerAdapter.bitmapsHalfScreenWidthArrayList.get(i).isRecycled()) {
recyclerAdapter.bitmapsHalfScreenWidthArrayList.get(i).recycle();
recyclerAdapter.bitmapsHalfScreenWidthArrayList.remove(i);
recyclerAdapter.bitmapsHalfScreenWidthArrayList.add(i, null);
}
}
for (int i = 0; i < howManyBitmaps; i++) {
if (recyclerAdapter.bitmapsFullScreenWidth.get(i) != null && ! recyclerAdapter.bitmapsFullScreenWidth.get(i).isRecycled()) {
recyclerAdapter.bitmapsFullScreenWidth.get(i).recycle();
recyclerAdapter.bitmapsFullScreenWidth.remove(i);
recyclerAdapter.bitmapsFullScreenWidth.add(i, null);
}
}
}
然后java.lang.OutOfMemoryError
没有出现,但我必须在onResume()
中初始化RecylerView的适配器,以避免Canvas: trying to use a recycled bitmap android.graphics.
错误,这意味着如果用户离开应用程序在此活动中,适配器必须在重新进入该活动后重新初始化,并且最好在每次调用onPause()时解决java.lang.OutOfMemoryError
而不回收位图。
我不愿意缓存Bitmaps,因为这可能会使Activity的其余部分执行得不那么顺利。
我的问题简而言之
如果我的Activity能够成功加载Bitmaps而不会因为java.lang.OutOfMemoryError而崩溃,直到我重新启动Activity multiple,那么当我的Activity重新启动时避免java.lang.OutOfMemoryError
的最佳方法是什么多次?
提前致谢
编辑 Glide库能够在这里解决OOM问题,但是当RecyvlerView滚动时,它会导致一些RecyclerView的图像消失,尽管它们被重新加载 - 但这可能是可以解决的