Android 大图导致OOM

图片过大导致OOM,这里使用LuBan方案,LuBan是基于微信压缩逆推出来的方案,有兴趣可以自行去了解

//使用的依赖

implementation 'top.zibin:Luban:1.1.8'

 接口回调类,封装LuBan 压缩成功后回调方法,可自行定制代码

public interface CompressionCallback {
   void onCompressed(File compressedFile) throws FileNotFoundException;
   void onFailure(String errorMessage);
}

 封装LuBan

public class LuBanUtils {
   private final Context context;
   private final int SIZE = 1;
   private final String TAG = "LuBanError";

   public LuBanUtils(Context context) {
      this.context = context;
   }


   public void compressImageWithLuBan(InputStream inputStream, final CompressionCallback callback,String FileName){
      File targetFile = new File(context.getFilesDir(), FileName+".jpg");

      try {
         FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
         byte[] buffer = new byte[1024];
         int length;
         while ((length = inputStream.read(buffer)) > 0) {
            fileOutputStream.write(buffer, 0, length);
         }
         fileOutputStream.close();
         inputStream.close();

         Luban.with(context)
               .load(targetFile)
               .setCompressListener(new OnCompressListener() {
                  @Override
                  public void onStart() {
                     // 压缩开始,可以在这里显示进度条等操作
                  }

                  @Override
                  public void onSuccess(File compressedFile) {
                     // 压缩成功,调用成功回调方法
                     try {
                        String path = compressedFile.getPath();
                        Log.i(TAG, "onSuccess: "+path);
                        callback.onCompressed(compressedFile);
                     } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                     }
                  }

                  @Override
                  public void onError(Throwable e) {
                     // 压缩失败,调用失败回调方法
                     callback.onFailure(e.getMessage());
                  }
               })
               .launch();

      } catch (IOException e) {
         e.printStackTrace();
         callback.onFailure(e.getMessage());
      }
   }
  
//  public void Destroy(){
//    String path ="/storage/emulated/0/Android/data/com.example.demo_image/cache/luban_disk_cache/";
//    File cacheDir = new File(path);
//    if (cacheDir.isDirectory()) {
//       File[] files = cacheDir.listFiles();
//       if (files != null) {
//          for (File file : files) {
//             if (file.isFile()) {
//                file.delete();
//             }
//          }
//       }
//    }
// }

   
   public void Destroy(){
      AsyncTaskDel asyncTaskDel=new AsyncTaskDel();
      asyncTaskDel.execute();
   }
   public class AsyncTaskDel extends AsyncTask{

      @Override
      protected Object doInBackground(Object[] objects) {
         String path ="/storage/emulated/0/Android/data/"+context.getPackageName()+"/cache/luban_disk_cache/";
         Log.d(TAG, "Destroy: "+context.getPackageName());
         File cacheDir = new File(path);
         if (cacheDir.isDirectory()) {
            File[] files = cacheDir.listFiles();
            if (files != null) {
               for (File file : files) {
                  if (file.isFile()) {
                     file.delete();
                  }
               }
            }
         }
         return null;
      }
   }
}

 注意的是LuBan不能直接压缩图片,他是转成file形式再压缩的,同时会产生对应的缓存文件,需要及时删除缓存文件,不然长期使用会出现磁盘占用过大的情况

Activity里调用

public class MainActivity extends AppCompatActivity {

   private TextView text;
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      initView();
      LuBanUtils luBanUtils=new LuBanUtils(this);
      @SuppressLint("ResourceType") InputStream inputStream = getResources().openRawResource(R.drawable.err);
      luBanUtils.compressImageWithLuBan(inputStream, new CompressionCallback() {
         @Override
         public void onCompressed(File compressedFile) throws FileNotFoundException {
            // 在这里处理压缩后的文件
            Uri uri = Uri.fromFile(compressedFile);
            // 使用URI创建Drawable对象
            Drawable drawable = Drawable.createFromStream(getContentResolver().openInputStream(uri), uri.toString());
            text.setBackground(drawable);
         }

         @Override
         public void onFailure(String errorMessage) {
            // 在这里处理压缩失败的情况
         }
      },"eee");//名称自己传参数,不然部分设备会出现加载多张图片出现一样的情况,图片名字要不同
   }

   private void initView() {
      text = (TextView) findViewById(R.id.text);
   }

   @Override
   protected void onDestroy() {
      super.onDestroy();
      LuBanUtils luBanUtils=new LuBanUtils(MainActivity.this);
      luBanUtils.Destroy();
   }
}

压缩效果还是很可观的,比自己手打bitmap强多了,手打bitmap会出现很多问题,没有及时回收bitmap的话压缩后占用还会比压缩前占用的多

直接添加背景图片占用 29.3

使用luban压缩后App内存19.6

一张图片内存压缩快到了10m大小,效果还是非常可观的

* 2024.1.19更新

1.自动获取包名,自动获取缓存路径,调用Destroy时 自动获取文件包名缓存路径删除缓存文件,适合退出Actviity时候使用,在onDestroy里调用

2.异步调用删除功能,防止缓存图片过多删除时候导致ANR或严重卡顿

*2024.2.1更新

1.修复文件缓存名称的问题,部分设备会出现加载图片错误的问题,出现多张相同的图片

*2024.2.2发现BUG

1.压缩图标类图片,透明边框解压出来再添加进去,透明边框变成黑色边框,

   解决方案,重新截图带上边框颜色(目前想到的比较快的方案)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值