图片过大导致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.压缩图标类图片,透明边框解压出来再添加进去,透明边框变成黑色边框,
解决方案,重新截图带上边框颜色(目前想到的比较快的方案)