当前位置:首页 > 行业动态 > 正文

安卓压缩网络图片

安卓压缩网络图片可通过BitmapFactory.Options设置inSampleSize采样 压缩,结合质量压缩算法,或使用Glide/Picasso库自动优化,需注意保持宽高比

获取网络图片

在安卓中获取网络图片通常使用第三方库(如Glide、Picasso)或手动通过OkHttpRetrofit下载,以下以手动下载为例:

// 使用OkHttp下载图片
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://example.com/image.jpg").build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 处理失败
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        InputStream inputStream = response.body().byteStream();
        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
        // 后续压缩处理
    }
});

压缩图片的核心方法

尺寸压缩(按比例缩放)

通过BitmapFactory.OptionsinSampleSize参数减少内存占用:

安卓压缩网络图片

public static Bitmap decodeSampledBitmap(InputStream is, int reqWidth, int reqHeight) {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, options);
    // 计算采样率
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(is, null, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    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;
        while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize = 2;
        }
    }
    return inSampleSize;
}

质量压缩(降低文件大小)

通过Bitmap.compress()方法调整JPEG质量:

安卓压缩网络图片

public static byte[] compressBitmap(Bitmap bitmap, int quality) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
    return baos.toByteArray();
}

完整压缩流程示例

// 异步任务处理压缩
class CompressTask extends AsyncTask<InputStream, Void, byte[]> {
    @Override
    protected byte[] doInBackground(InputStream... inputs) {
        try {
            // 1. 尺寸压缩
            Bitmap bitmap = decodeSampledBitmap(inputs[0], 800, 600);
            // 2. 质量压缩
            return compressBitmap(bitmap, 80); // 质量参数范围:0-100
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    @Override
    protected void onPostExecute(byte[] result) {
        // 保存或上传压缩后的图片
    }
}

内存优化技巧

优化方式 说明
inSampleSize 通过采样率降低Bitmap内存占用
Bitmap.recycle() 手动回收不再使用的Bitmap对象
LruCache 使用缓存避免重复解码
WebP格式 采用更高效的图片编码格式

常见问题与解决方案

问题 解决方案
OOM错误 使用inSampleSize
分区域加载(BitmapRegionDecoder
启用大内存模式(Android 11+)
压缩后模糊 适当提高quality参数
优先保证尺寸压缩比例合理
性能瓶颈 使用Glide/Picasso代替手动处理
开启多线程压缩

相关问题与解答

Q1:如何缓存压缩后的图片?

A:可结合DiskLruCache或第三方库(如Glide)实现持久化缓存:

// 使用Glide缓存(自动处理内存和磁盘缓存)
Glide.with(context)
     .load("https://example.com/image.jpg")
     .override(800, 600) // 尺寸限制
     .diskCacheStrategy(DiskCacheStrategy.ALL) // 强制缓存
     .into(imageView);

Q2:如何处理动态图片(如GIF)的压缩?

A:动态图片需特殊处理:

安卓压缩网络图片

  1. 不压缩动画帧:直接存储原始GIF(可用GlideasGif()方法)
  2. 转静态图:提取单帧后按静态图压缩,但会丢失动画效果
  3. 使用WebP格式:支持动态图片且体积更小(需系统支持)