我创建了一个BitmapPool,如下所示。
public class BitmapPool {
private HashMap<Integer, Progress> progMap = new HashMap<Integer, Progress>();
private HashMap<Integer, Bitmap> bitmaps = new HashMap<Integer, Bitmap>();
private BitmapPool() {
}
private static BitmapPool sInstance;
public static synchronized BitmapPool getInstance() {
if (sInstance == null) {
synchronized (BitmapPool.class) {
sInstance = new BitmapPool();
}
}
return sInstance;
}
public synchronized Bitmap getBitmap(byte[] data, int frameNo) {
ArrayList<Integer> reUseableKeyList = getReuseableBitmapKeyList();
if (reUseableKeyList.size() == 0) {
return getNewBitmap(data, frameNo);
} else {
return getAndReuseOldBitmap(data, frameNo, reUseableKeyList);
}
}
private synchronized Bitmap getNewBitmap(byte[] data, int frameNo) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inMutable = true;
options.inSampleSize = 1;
Bitmap newBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
progMap.put(frameNo, Progress.INIT_FRAME);
bitmaps.put(frameNo, newBitmap);
return newBitmap;
}
private synchronized Bitmap getAndReuseOldBitmap(byte[] data, int frameNo, ArrayList<Integer> reUseableKeyList) {
// iterate over keyList to check if old bitmap can be used
for (Integer key : reUseableKeyList) {
Bitmap b = bitmaps.get(key);
// get target bitmap bounds for comparing
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
if (canUseForInBitmap(b, options)) {
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inMutable = true;
options.inBitmap = b;
options.inJustDecodeBounds = false;
Bitmap newBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
progMap.remove(key);
progMap.put(frameNo, Progress.INIT_FRAME);
bitmaps.remove(key);
bitmaps.put(frameNo, newBitmap);
b = null;
return newBitmap;
}
}
// no old bitmap could be used > return new bitmap
return getNewBitmap(data, frameNo);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public synchronized boolean canUseForInBitmap(
Bitmap candidate, BitmapFactory.Options targetOptions) {
// From Android 4.4 (KitKat) onward we can re-use if the byte size of
// the new bitmap is smaller than the reusable bitmap candidate
// allocation byte count.
int width = targetOptions.outWidth / targetOptions.inSampleSize;
int height = targetOptions.outHeight / targetOptions.inSampleSize;
int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
try {
return byteCount <= candidate.getAllocationByteCount();
} catch (NullPointerException e) {
return byteCount <= candidate.getHeight() * candidate.getRowBytes();
}
}
private synchronized ArrayList<Integer> getReuseableBitmapKeyList() {
ArrayList<Integer> list = new ArrayList<>();
for (Map.Entry entry : progMap.entrySet()) {
if (entry.getValue() == Progress.FAILED || entry.getValue() == Progress.USED)
list.add((int) entry.getKey());
}
return list;
}
private int getBytesPerPixel(Bitmap.Config config) {
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
int bytesPerPixel;
switch (config) {
case ALPHA_8:
bytesPerPixel = 1;
break;
case RGB_565:
case ARGB_4444:
bytesPerPixel = 2;
break;
case ARGB_8888:
default:
bytesPerPixel = 4;
break;
}
return bytesPerPixel;
}
public void terminate() {
for (Bitmap b : bitmaps.values()) {
b.recycle();
b = null;
}
}
}
我正在检查使用标准代码,如果位图已准备好重复使用,然后将其与inBitmap选项一起使用。这是在多线程环境中完成的。
奇怪的是我得到: 致命信号11(SIGSEGV),BitmapFactory.decodeByteArray()中的代码1 在getAndReuseOldBitmap()。
我无法找出原因。
有人请帮忙。