1、问题
新版本上线后, 后台出现了java.lang.NullPointerException报错,异常发生在RelativeLayout的measure( )方法内部,measure( )方法调用方式如下:
// 实例化一个RelativeLayout对象
mDefaultView = LayoutInflater.from(getContext()).inflate(R.layout.facebook_following_layout, null);
// 调用measure()手动测量长宽,异常就是因为调用measure()
mDefaultView.measure(0, 0);
// 添加父容器中
mParent.addView(mDefaultView);
为何调用measure()会抛异常呢?
2、分析
通过观察发现在Android4.3以下(含4.3)的设备才出现异常,于是查看Android4.3版本的RelativeLayout的代码,出现空指针的地方如下:
/ 就是mLayoutParams为null导致mLayoutParams.width出现异常
f (mLayoutParams.width >= 0) {
width = Math.max(width, mLayoutParams.width);
}
先不分析为何mLayoutParams会为null,我们看一下Android4.3以上的版本
// 4.3以上因为对mLayoutParams做了判空操作,所以才避免了空指针异常
if (mLayoutParams != null && mLayoutParams.width >= 0) {
width = Math.max(width, mLayoutParams.width);
}
现在已找到我们上面调用measure( )方法为何4.3以下版本会报错,而4.3以上的版本不会报错的原因。
现在需要分析为何mLayoutParams会为空呢?
mLayoutParams是一个View在父容器中的布局参数,但我们通过mDefaultView = LayoutInflater.from(getContext()).inflate(R.layout.facebook_following_layout, null);
来实例化一个RelativeLayout对象mDefaultView时,mDefaultView还未被添加到父容器中,所以mDefaultView中mLayoutParams还是个空值。
解决方案1:先把View添加父容器后再进行测量
mDefaultView = LayoutInflater.from(getContext()).inflate(R.layout.facebook_following_layout, null);
// 先把mDefaultView先添加到父容器中,这样mLayoutParams就不会为null
mParent.addView(mDefaultView);
// 先添加父容器后再进行测量
mDefaultView.measure(0, 0);
解决方案2:在实例化RelativeLayout对象mDefaultView时,就给mDefaultView对象创建一个mLayoutParams参数
// 在inflate()方法通过设定参数为mDefaultView创建mLayoutParams布局参数
mDefaultView = LayoutInflater.from(getContext()).inflate(R.layout.facebook_following_layout, this, false);
mDefaultView.measure(0, 0);
addView(mDefaultView);