一个意想不到的crash


先给大家上一段代码:

    ConnectivityManager conmgr = (ConnectivityManager) MovieProApplication.getContext()
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (conmgr.getActiveNetworkInfo() == null) {
        return NETWORK_UNKOWN;
    }
    switch (conmgr.getActiveNetworkInfo().getType())      {
        case ConnectivityManager.TYPE_WIFI:
            netWorkType = NETWORK_WIFI;
            break;
   }
   return netWorkType;

这段代码是读取网络状态。但能看出来这里隐藏着一个空指针异常吗(虽然出现的几率很低),这个crash的日志如下

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.net.NetworkInfo.getType()' on a null object reference
	at com.sankuai.moviepro.utils.bk.c(MovieUtils.java:783)
	at com.sankuai.moviepro.utils.c.b.d(ImageQualityUtil.java:265)
	at com.sankuai.moviepro.utils.c.b.c(ImageQualityUtil.java:221)
	at com.sankuai.moviepro.utils.c.b.d(ImageQualityUtil.java:294)
	at com.sankuai.moviepro.utils.c.b.b(ImageQualityUtil.java:83)
	at com.sankuai.moviepro.utils.c.b.a(ImageQualityUtil.java:120)
	at com.sankuai.moviepro.views.custom_views.by.onPreDraw(RemoteImageView.java:104)

报异常的位置是switch (conmgr.getActiveNetworkInfo().getType()),按照正常的思维,会想,我们在上面不是已经判断,为空的时候不是return了么,但事实就是这么巧两次执行conmgr.getActiveNetworkInfo()的结果如果不同呢,你会发现在上面判断不为空,在下面使用的时候就空指针了。有人会说这个几率很低,但如果这个方法比较耗时呢,读取的状态不同也就很正常了,分析完我们也可以复现这个crash了,在switch前打一个断点,然后切断网络,然后继续debug,然后就崩溃了。

解决的方法很简单,我们预先把这个读取出来,我们判断和使用的都是这个预先读取出来的networkInfo,这样就不会出现前后读取不一致的结果了。

NetworkInfo networkInfo = conmgr.getActiveNetworkInfo();


本作品由 Tony Zhang 创作,采用 CC BY-NC-SA 3.0 许可协议 进行许可。

Comments