Android多图上传时,为了防止内存溢出,基本只要做好两点就好了,一是及时释放已经上传完的图片,以及在对图片处理时,必须是一张一张来,因为对图片的处理过程是最容易OOM的。
下面有简单的代码说明下,
1、首先,图片的model,
ImageBean
model中保存bitmap对象,然后写好回收方法。
然后,上传大致分为路径上传,还有压缩后以byte[]的方式上传,
所以也要有path和byte[]
public String path;
public Bitmap bitmap;
public byte[] result;
public Bitmap getBitmap() {
if (bitmap == null || bitmap.isRecycled()) {
try {
//bitmap = MyBimp.revitionImageSize(path, rotation);
bitmap = MyBimp.getBitmapFromFile(path, rotation);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return bitmap;
}
public void recy() {
if (bitmap != null) {
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
bitmap = null;
}
if (result != null)
result = null;
}
public static byte[] Bitmap2Bytes(Bitmap image, long size) {
try {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
long max = 1024 * 1024 + 3072;
if (size > max) {
int options = 100;
while (baos.toByteArray().length > (size * 0.8)) {
baos.reset();
options -= 10;
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
// Log.i("TAG", "Utils bitmap option " + options);
if (image.isRecycled())
image.recycle();
return baos.toByteArray();
} else {
return baos.toByteArray();
}
} catch (NullPointerException ex) {
ex.printStackTrace();
}
} catch (OutOfMemoryError ex) {
ex.printStackTrace();
}
return null;
}
<pre name="code" class="java"> public static Bitmap getBitmapFromFile(String path, int rotation) throws IOException {
if (path == null)
return null;
try {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(
new File(path)));
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
WeakReference<Bitmap> weakReference = new WeakReference<Bitmap>(BitmapFactory.decodeFile(path));
if (weakReference.get() != null) {
Bitmap bitmap = Bitmap.createScaledBitmap(weakReference.get(), options.outWidth, options.outHeight, true);
if (rotation != 0 && bitmap != null) {
Matrix m = new Matrix();
m.setRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
}
return bitmap;
}
} catch (NullPointerException ex) {
ex.printStackTrace();
}
} catch (OutOfMemoryError ex) {
ex.printStackTrace();
}
return null;
}
压缩程度根据自己项目实际情况来控制。
2、从相册读取图片,应该只读取了手机中图片的路径等相关信息,然后压缩显示,这些代码往上非常多。
目的只有一个,不占用多余的内存,
所以只有真正要上传的图片,才会生成完整的bitmap对象或byte[]数组。
可以创建一个全局的MyBimp类,用来管理相册图片,已选择的图片等等。
public static ArrayList<ImageBean> tempSelectBitmap = new ArrayList<ImageBean>();
选择完图片后,应该是一个List<ImageBean>数组。3、上传,保证单例上传,然后每上传完一个调用model中的回收方法就好了,
public class UploadTool {
private static UploadTool uploadTool = null;
private UploadTool() {
}
public static UploadTool getInstance() {
if (uploadTool == null) {
uploadTool = new UploadTool();
}
return uploadTool;
}
int len;// = MyBimp.tempSelectBitmap.size();
List<ImageModel> list = new ArrayList<>();
int position;
private synchronized void upload(final int next, final onUploadImagesListenter listenter) {
listenter.onProgressUpdate(next, len);
if (next < len) {
ImageBean item = MyBimp.tempSelectBitmap.get(next);
if (next > 0) {
MyBimp.tempSelectBitmap.get(next - 1).recy();
}
if (!item.isLarge) {
item.getBitmapLocal(new ImageBean.onBitmapLoadListener() {
@Override
public void onBitmapLoad(byte[] result) {
if (result != null) {
//以byte[]上传
} else {
String error = "数据错误";
listenter.onUploadDone(list, error);
}
}
});
} else {
//以路径上传 一般长图会以这种方式上传
}
}
}
public void uploadImages(final onUploadImagesListenter listenter) {
len = MyBimp.tempSelectBitmap.size();
position = 0;
upload(0, listenter);
}
public interface onUploadImagesListenter {
void onUploadDone(List<ImageModel> imageModelList, String error);
void onProgressUpdate(int position, int tatol);
}
}
具体的上传方法没有写进来,这个根据自己需求不同有很多种不同的方式,比如第三方的sdk。
源码:https://github.com/kiwilll/Album-and-Picture-upload