今天有朋友在群里说继承PopupWindow华为手机测试的时候实例化PopupWindow出现NullPointerException的错误。具体代码如下:
1 2 3 4 5 6
| public class MyPopup extends PopupWindow { private Context mContext; public MyPopup(Context context){ this.mContext = context; } }
|
错误信息如下:
在其他手机上运行是正常的,开始以为是华为手机的问题后来发现这款华为手机系统是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以上的没有问题。