使用ListView在Async Task中发生Java.Lang.OutOfMemoryError

时间:2014-07-03 11:53:31

标签: android listview android-listview android-asynctask baseadapter

我使用ListView的自定义适配器实施extends BaseAdapter。在我的应用中,图片从网址下载,然后在Listview中设置为位图图片。

问题是在完成2个图像的下载后java.Lang.OutOfMemoryError发生并且应用程序崩溃。我知道这是内存问题,但我不知道应该采取哪些步骤来避免这种情况......我使用压缩图像并且工作正常。

以下是getView() CustomAdapterdoInBackground() AsyncTask的代码。

提前谢谢......

任何建议都将受到赞赏..

public View getView(final int position, View convertView, final ViewGroup parent) {


      if (convertView == null){          
          convertView = inflater.inflate(R.layout.row, parent, false);  

      }

        img_name = "test" + position;
        image = (ImageView) convertView.findViewById(R.id.imageView1);
        Log.d("URL", ""+values[position]);
        AsyncTaskRunner runner = new AsyncTaskRunner();
        final int x = (int) getItemId(position);
        runner.execute(values[x] , image , img_name);


      return convertView;
    }

doInBackground(对象...参数)

protected ImageView doInBackground(Object... params) {
              //publishProgress("Calculating..."); // Calls onProgressUpdate()
           URL imageURL = null;

           try {
            url = (String) params[0];
            img = (ImageView) params[1];
            name = (String) params[2] + ".png";
            imageURL = new URL(url); 
            Log.d("URL", ""+params[0]);
            }

           catch (MalformedURLException e) {
               e.printStackTrace();
            }

           try {
            HttpURLConnection connection= (HttpURLConnection)imageURL.openConnection();
            connection.setDoInput(true);
            connection.connect();

            InputStream inputStream = connection.getInputStream();

            bitmap = BitmapFactory.decodeStream(inputStream);
            resized = Bitmap.createScaledBitmap(bitmap, 200, 200, true);


           }
           catch (IOException e) {

                e.printStackTrace();
           }

           return img;
          }

OnPostExecute(ImageView结果)

  protected void onPostExecute(ImageView result) {
              result.setImageBitmap(resized);
          }

3 个答案:

答案 0 :(得分:2)

  

java.Lang.OutOfMemoryError

<强>原因:

android中的每个进程都分配了一个不同的最大堆大小 设备到设备。(平均约16 MB。)在应用程序中使用的高分辨率图像占用此堆的大空间。因此,当创建新的位图实例并且总大小超过分配的堆大小时,是JVM抛出的错误。

<强>解决方案:

Android提供了一种处理此问题的方法。在解码位图之前,我们只需使用options.inJustDecodeBounds = true.对其进行解码,其中options是BitmapFactory的实例。它不会将位图加载到内存中,但它可以帮助我们找到位图的宽度和高度,以便我们可以根据设备减小高度和宽度。

然后缩小您的位图以创建一个较小尺寸的图像,这反过来会占用堆上较少的空间。 这是实现它的方法。

BitmapFactory.Options bmpBuffer = new BitmapFactory.Options(); 
bmpBuffer.inSampleSize = 3; 
Bitmap bmp = BitmapFactory.decodeFile(path, bmpBuffer); 

这将使您的位图成为原始大小的1/3 rd因此 也会占据1/3的空间。

<强>例如

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

  // First decode with inJustDecodeBounds=true to check dimensions
  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;        
  BitmapFactory.decodeResource(res, resId, options);

  // Calculate inSampleSize
  options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

  // Decode bitmap with inSampleSize set
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeResource(res, resId, options);
}

计算样本量的方法:

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) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}

注意:

如果没有其他选项,您可以使用以下内容。但是,我想提醒您,它会影响您设备上的其他应用程序。因此我不建议你使用它。

<application
        android:largeHeap="true">
</application>

largeHeap="true"将允许应用程序使用更多堆(如果可用)。但是,您的应用程序将在垃圾收集期间花费更多时间。设备上的其他应用程序可能会被踢出内存。

CommonsWare 解释了它here

答案 1 :(得分:0)

您可以使用Picasso Library有效地从网址下载图片,此外还有更多选项可以调整图片大小,缓存等。

答案 2 :(得分:0)

使用此bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

相关问题