赞
踩
Lottie 是在 Android 和 iOS上 原生渲染 的After Effects(AE)动画,Lottie是 Airbnb 开源 的支持Android 和 iOS 的动画库,它可以解析 AE 动画中用Bodymovin 导出的json文件,并在移动设备上利用原生库进行渲染 !项目地址:https://github.com/airbnb/lottie-android
Lottie框架帮我们解决很多过场动画和图标点击动画这些应用场景,可能是因为太好用了,最近一个版本的UI大量使用到了lottie动画,这个时候问题就出现了,使用Profiler进行内存检测的时候,发现了Native Heap 内存可以飙升到1GB,Android 8.0之后Bitmap 像素占用的内存分配到了 Native Heap中(目前主流用户大部分都在8.0以上的版本了),基本上就可以确定就是lottie框架加载动效太多造成的,那么我们就来清除Bitmap的缓存吧
根据阅读源码可以
LottieAnimationView 是主要进行属性设置以及状态管理的,我们来看invalidateDrawable方法
@Override
public void invalidateDrawable(@NonNull Drawable dr) {
if (getDrawable() == lottieDrawable) {
// We always want to invalidate the root drawable so it redraws the whole drawable.
// Eventually it would be great to be able to invalidate just the changed region.
// 绘制lottie动画
super.invalidateDrawable(lottieDrawable);
} else {
// Otherwise work as regular ImageView
super.invalidateDrawable(dr);
}
}
由于后续的源码调用的链路是这样子的LottieDrawbale.draw(canvas)–》CompositionLayer.draw - 》 BaseLayer.draw -》 ImageLayer.draw ,我们来看看ImageLayer的源码
@Override public void drawLayer(@NonNull Canvas canvas, Matrix parentMatrix, int parentAlpha) { Bitmap bitmap = getBitmap(); if (bitmap == null || bitmap.isRecycled()) { return; } float density = Utils.dpScale(); paint.setAlpha(parentAlpha); if (colorFilterAnimation != null) { paint.setColorFilter(colorFilterAnimation.getValue()); } canvas.save(); canvas.concat(parentMatrix); src.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); dst.set(0, 0, (int) (bitmap.getWidth() * density), (int) (bitmap.getHeight() * density)); canvas.drawBitmap(bitmap, src, dst , paint); canvas.restore(); }
那么getBitmap()方法是调用的ImageAssetManager.bitmapForId
@Nullable public Bitmap bitmapForId(String id) { LottieImageAsset asset = imageAssets.get(id); if (asset == null) { return null; } Bitmap bitmap = asset.getBitmap(); // 检测bitmap是否已经回收 if (bitmap != null && !bitmap.isRecycled()) { return bitmap; } if (delegate != null) { bitmap = delegate.fetchBitmap(asset); if (bitmap != null) { putBitmap(id, bitmap); } return bitmap; } String filename = asset.getFileName(); BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inScaled = true; opts.inDensity = 160; if (filename.startsWith("data:") && filename.indexOf("base64,") > 0) { // Contents look like a base64 data URI, with the format data:image/png;base64,<data>. byte[] data; try { data = Base64.decode(filename.substring(filename.indexOf(',') + 1), Base64.DEFAULT); } catch (IllegalArgumentException e) { Logger.warning("data URL did not have correct base64 format.", e); return null; } bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts); return putBitmap(id, bitmap); } InputStream is; try { if (TextUtils.isEmpty(imagesFolder)) { throw new IllegalStateException("You must set an images folder before loading an image." + " Set it with LottieComposition#setImagesFolder or LottieDrawable#setImagesFolder"); } is = context.getAssets().open(imagesFolder + filename); } catch (IOException e) { Logger.warning("Unable to open asset.", e); return null; } bitmap = BitmapFactory.decodeStream(is, null, opts); bitmap = Utils.resizeBitmapIfNeeded(bitmap, asset.getWidth(), asset.getHeight()); return putBitmap(id, bitmap); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。