我将使用下面的代码从服务器(URL)加载Adapter
的图像。它是新型移动设备的工作。然而,旧模型将崩溃并返回“java.lang.OutOfMemoryError
”。它会将A行或B行标记为错误。如何避免这个错误?或者还有其他图书馆来完成我的目标吗?请帮忙,谢谢!
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
ProgressBar progressBar;
public DownloadImageTask(ImageView bmImage, ProgressBar progressBar) {
this.bmImage = bmImage;
this.progressBar = progressBar;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in); //Line A
int resultWidth = mIcon11.getWidth();
int resultHeight = mIcon11.getHeight();
while(resultWidth > 256 && resultHeight > 256) {
resultWidth *= 0.5;
resultHeight *= 0.5;
}
mIcon11 = Bitmap.createScaledBitmap(mIcon11, (int) (resultWidth), (int) (resultHeight), true);
} catch (OutOfMemoryError e){
byte[] byteArr = new byte[0];
byte[] buffer = new byte[1024];
int len;
int count = 0;
InputStream in = null;
try {
in = new java.net.URL(urldisplay).openStream();
while ((len = in.read(buffer)) > -1) {
if (len != 0) {
if (count + len > byteArr.length) {
byte[] newbuf = new byte[(count + len) * 2]; //Line B
System.arraycopy(byteArr, 0, newbuf, 0, count);
byteArr = newbuf;
}
System.arraycopy(buffer, 0, byteArr, count, len);
count += len;
}
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(byteArr, 0, count, options);
options.inSampleSize = calculateInSampleSize(options, 256, 256);
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
mIcon11 = BitmapFactory.decodeByteArray(byteArr, 0, count, options);
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
progressBar.setVisibility(View.GONE);
progressBar.setIndeterminate(false);
bmImage.setVisibility(View.VISIBLE);
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
你可以使用GLIDE
。
阅读有关Loading Large Bitmaps
的官方指南。你应该RESIZE
图像。
要避免使用
java.lang.OutOfMemory
异常,请在解码之前检查位图的尺寸,除非您完全信任该源为您提供可预测大小的图像数据,这些数据可以轻松地放入可用内存中。
代码结构
- 从原件向下采样的位图,具有相同的宽高比和尺寸,等于或大于请求的宽度和高度
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
高分辨率位图的问题。您将减小大小或使用某些库进行位图加载,如Glide或Picasso。快速修复 - 您将在AndroidManifest中启用大堆:
<application
...
android:largeHeap="true"
将此添加到您的gradle中
android
{
dexOptions
{
javaMaxHeapSize "4g" //specify the heap size for the dex process
}
}