在新版LottieAnimationView的开源项目中,如果在xml中设置了src属性则会引发空指针异常,导致崩溃。
如下图所示,错误的设置方法:
![](https://img.haomeiwen.com/i4429036/7e5768831d45d168.png)
崩溃日志如下
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.airbnb.lottie.LottieDrawable.recycleBitmaps()' on a null object reference
at com.airbnb.lottie.LottieAnimationView.recycleBitmaps(LottieAnimationView.java:256)
at com.airbnb.lottie.LottieAnimationView.setImageDrawable(LottieAnimationView.java:176)
at com.airbnb.lottie.LottieAnimationView.setImageDrawable(LottieAnimationView.java:171)
原因很简单 LottieAnimationView 是继承自 AppCompatImageView:
public class LottieAnimationView extends AppCompatImageView{
而AppCompatImageView是继承自ImageView:
public class AppCompatImageView extends ImageView implements TintableBackgroundView,
TintableImageSourceView{
在ImageView的构造方法中会首先获取src属性 ,并通过调用setImageDrawable(Drawable drawable)方法来赋值:
public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
//之前的代码省略....
final Drawable d = a.getDrawable(R.styleable.ImageView_src);
if (d != null) {
setImageDrawable(d);
}
但是 坑来了!LottieAnimationView重写了setImageDrawable方法
private void setImageDrawable(Drawable drawable, boolean recycle) {
if (recycle && drawable != lottieDrawable) {
recycleBitmaps();
}
cancelLoaderTask();
super.setImageDrawable(drawable);
}
问题就出在了 recycleBitmaps()方法中,lottieDrawable这个时候还是null 源码中并没有防御代码:
@VisibleForTesting void recycleBitmaps() {
// AppCompatImageView constructor will set the image when set from xml
// before LottieDrawable has been initialized
lottieDrawable.recycleBitmaps();
}
但是看到之前的版本中,却是有防御性代码的 :
@VisibleForTesting void recycleBitmaps() {
// AppCompatImageView constructor will set the image when set from xml
// before LottieDrawable has been initialized
if (lottieDrawable != null) {
lottieDrawable.recycleBitmaps();
}
}
网友评论