Android从服务器下载图像并保存到SD卡而不使用BitmapFactory

vsa*_*tkh 5 java multithreading android imagedownload

我正在尝试创建一个用于从服务器下载图像并将其显示到listview的应用程序.我做的问题是内存泄漏并使我的应用程序崩溃.我在Android博客中搜索此链接,它显示了一个好主意,但仍然不足以用多个线程来做.android的某些设备可以使用它,但有些设备只能在单个线程中处理,有时它根本无法工作.

我的应用程序有很多活动,每个活动都有一个Listview,需要尽快显示图像.通过Google IO 2012,他们使用缓冲区将原始图像保存到SD卡,它解决了泄漏内存的问题,但由于需要下载的图像太大,导致加载速度变慢.

我的问题是:有没有办法将图像与写入SD卡一起缩放? 我想出一些可能的解决方案是在输入流对象中使用跳过字节,我能够找到我需要下载的图像的每像素宽度和高度.

以下代码在Google IO 2012中使用,它适用于多线程,在我的情况下,我有4个线程在后台运行.

private void downloadAndWriteFile(final String url, final File file) throws OutOfMemoryError {
    BufferedOutputStream out = null;

    try {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setDoInput(true);
        conn.connect();

        final InputStream in = new BufferedInputStream(conn.getInputStream(), IO_BUFFER_SIZE_BYTES);    // buffer size 1KB
        out = new BufferedOutputStream(new FileOutputStream(file), IO_BUFFER_SIZE_BYTES);

        int b;
        while ((b = in.read()) != -1) {
            out.write(b);
        }
        out.close();
        conn.disconnect();
    }
    catch (Exception e) {
        Log.e(TAG, "!!downloadAndWriteFile " + e.getMessage());
        file.delete();
    }
}
Run Code Online (Sandbox Code Playgroud)

Bob*_*obs 1

1) 在设置图像之前使用以下代码来释放与该位图关联的本机对象,并清除对像素数据的引用。如果没有其他引用,它只是允许它被垃圾收集。

BitmapDrawable drawable = (BitmapDrawable) myImage.getDrawable();
Bitmap bitmap = drawable.getBitmap();
if (bitmap != null)
{
    bitmap.recycle();
}
Run Code Online (Sandbox Code Playgroud)

2)使用此方法来减少内存中位图的大小:

/**
 * decodes image and scales it to reduce memory consumption
 * 
 * @param file
 * @param requiredSize
 * @return
 */
public static Bitmap decodeFile(File file, int requiredSize) {
    try {

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(file), null, o);

        // The new size we want to scale to

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < requiredSize
                    || height_tmp / 2 < requiredSize)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;

        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(file),
                null, o2);

        return bmp;

    } catch (FileNotFoundException e) {
    } finally {
        System.gc();
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)