关于Android中PopupWindow在2.3以下使用出现NullPointerException的情况分析

今天有朋友在群里说继承PopupWindow华为手机测试的时候实例化PopupWindow出现NullPointerException的错误。具体代码如下:

1
2
3
4
5
6
public class MyPopup extends PopupWindow {
private Context mContext;
public MyPopup(Context context){
this.mContext = context;
}
}

错误信息如下:
11111

在其他手机上运行是正常的,开始以为是华为手机的问题后来发现这款华为手机系统是2.3的其他的都是2.3以上的,于是用2.3的模拟器运行了一次也出现错误了,看来是系统版本的问题。经过一整Google后发现网上也有人遇到这个问题,解决办法是在构造方法里加上super(context);

1
2
3
4
5
6
7
public class MyPopup extends PopupWindow {
private Context mContext;
public MyPopup(Context context){
super(context);
this.mContext = context;
}
}

这样即可解决在2.3上以下出现NullPointerException的情况了。问题是解决了,可是是为什么呢?接下来我们分析以下。
当我们继承PopupWindow后new一个MyPopup的时候首先会调用PopupWindow的构造方法:

1
2
3
public PopupWindow() {
this(null, 0, 0);
}

然后继续:

1
2
3
public PopupWindow(View contentView, int width, int height) {
this(contentView, width, height, false);
}

继续跟下去:

1
2
3
4
5
6
7
8
9
10
public PopupWindow(View contentView, int width, int height, boolean focusable) {
if (contentView != null) {
mContext = contentView.getContext();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
setContentView(contentView);
setWidth(width);
setHeight(height);
setFocusable(focusable);
}

然后我们看setContentView里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 public void setContentView(View contentView) {
if (isShowing()) {
return;
}

mContentView = contentView;

if (mContext == null) {
mContext = mContentView.getContext();
}

if (mWindowManager == null) {
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
}

相信大家都看到问题所在了,这里的context是null,然后执行了mContext = mContentView.getContext()而contentview我们还没有设置也为null,所以报NullPointerException。而加上super(context)后实例化PopupWindow的时候调用的是PopupWindow的:

1
2
3
public PopupWindow(Context context) {
this(context, null);
}

故不会出现问题。
接下来我们再来看一下4.0的setContentView:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  public void setContentView(View contentView) {
if (isShowing()) {
return;
}

mContentView = contentView;

if (mContext == null && mContentView != null) {
mContext = mContentView.getContext();
}

if (mWindowManager == null && mContentView != null) {
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
}

4.0的多加了一个contentview的非空判断,所以4.0以上的没有问题。

坚持原创技术分享,您的支持将鼓励我继续创作!