13、主线程任务太多导致异常退出(The application may be doing too much work on its main thread)
今天花费了一天的时间来解决这个bug。
这种在程序运行期间出现的问题比较棘手,如果再没有规律的话就更难解决。
还好这个bug是由规律的,也就是说在程序执行半个小时左右后就会因为此异常而导致程序退出;那么在网上找了下原因,无非是说一下几点:
1、把业务放在子线程中去完成,然后通过handler来更新界面
2、通过runOnUiThread的方法来实现
再补充一点就是:优化代码,将不需要重复执行的代码执行一次就ok了,特别是需要绘制UI的代码更不能随便放在重复执行的地方
一、bug现场还原
我的程序就是类似一个会自动播放图片的网络图片浏览器
通过定时器来每隔10s去执行一次图片的网络请求,得到图片后设置为imagview将要显示的图片;通过这两步基本就完成基本需求了。
但是当程序在运行30分钟,也就是播放了100多张不同的照片后,出现了“Skipped 62 frames! The application may be doing too much work on its main thread”这样的bug,同时还伴随“GC_FOR_ALLOC freed 2755K, 18% free 13874K/16884K, paused 3753ms, total 3756ms”这样的错误
二、bug出现的原因
从报出的异常本身来说,意思就是主线程任务太重,内存耗用太多。但是我用的是BitmapUtils这个工具库,只有第一次会进行网络请求,之后就会用默认的缓存数据
所以说问题肯定不在网络请求数据这块,那就是在imageVIew设置图片资源这里。
仔细看看,不应该有问题啊,就这几个代码:
1 linearParams = new RelativeLayout.LayoutParams( 2 CommonUtils.getScreenWidth(contextShowCall), CommonUtils.getScreenHeight(contextShowCall)); 3 imageView.setLayoutParams(linearParams);
4 String imgUrl = "http://"+QiNiuBucketName+".com1.z0.glb.clouddn.com/image-"+pic_casted_index+".jpg"; 5 6 relativeLayoutShowCall.setBackgroundDrawable(new BitmapDrawable(lastBitMap)); 7 bitmapUtils.display(imageView, imgUrl, bigPicDisplayConfig, callback);
从代码上来看,前3行的代码,在imageView在程序其他地方没有对其修改的前提下,是不用重复设置的。将前三行代码放到程序初始化的地方,再运行程序后,发现运行2小时内暂时未发现问题。
问题锁定在了这3行代码:重复从内存中申请变量,重复设置控件的宽度和高度,再加上必须得重绘图片,对于主线程来说确实任务较重,那么通过将调整代码后确实减轻了主线程的任务量(只是重绘imageView的图片就可以了)。
总结:
1、对于在程序运行期间出现的bug,要寻找规律,寻找规律的方法之一就是在多个设备同时执行同一程序,进而快速定位错误出现的时间点和错误日志
2、最好是在程序异常时能够保证100%将异常数据发送到开发者邮箱或者管理工具,很抱歉,我还没找到一款能符合条件的(国外的mint splunk、国内的友盟都做不到100%)
3、eclipse的logcat默认只可以缓存5000条数据,可以这样设置,从而方便查看系统log: