[异常特工]android常见bug跟踪
前言
对app的线上bug的收集(友盟、云捕等)有时会得到这样的异常堆栈信息:没有一行代码是有关自身程序代码的。这使得对bug的解决无从下手,根据经验,内存不足OOM,Dialog关闭,ListView等相关代码很容易引起这类错误。下面总结下BaseAdapter.getView崩溃bug,然后给出如何编写代码来方便以后对它的定位。
BaseAdapter.getView
如果getView方法返回null,那么对应的ListView在显示时就直接触发NullPointerException异常。但是无论是哪个界面的哪个ListView发生了这个错误,对应的异常信息总是这样的:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hxw.myapplication, PID: 1662
java.lang.NullPointerException
at android.widget.AbsListView.obtainView(AbsListView.java:2274)
at android.widget.ListView.makeAndAddView(ListView.java:1790)
at android.widget.ListView.fillDown(ListView.java:691)
at android.widget.ListView.fillFromTop(ListView.java:752)
at android.widget.ListView.layoutChildren(ListView.java:1630)
at android.widget.AbsListView.onLayout(AbsListView.java:2087)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1983)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1740)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
可以看到,整个异常信息提供的堆栈是不含任何与自己代码相关的调用信息的。
实际上,错误是因为getView返回null引起的,但是从上面的信息无法定位到到底哪个Adapter发生问题。
如果可以收集到用户是在哪个页面发生崩溃那么问题的定位会准确许多,但是,如果自己的Adapter需要返回好多种View(也就是getViewTypeCount的值,比如一个包含很多不同布局的对话列表),那么你还是需要仔细分析代码来找到具体哪个View的生成逻辑出了问题。
更多时候,除了得到以上的错误堆栈,对于真正的bug再无更多信息。实际上是无法判断出具体出问题的Adapter的。解决办法只能从根源上进行:
在我们编写getView方法时,对最终返回的参数自己进行非空判断,当针对不同position处的getItemViewType得到的View对象为null时,可以自己抛出一个NullPointerException,而不是等getView的调用者(框架API)来抛出上面给出的“没用”的信息。
也可以针对null的情况返回一个有用的信息给用户,而不是让程序崩溃。
// 在自己的Adapter子类中
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return buildView(position, convertView, parent);
}
private View buildView(int position, View convertView, ViewGroup parent) {
// ... 这里是根据getItemViewType生成不同View的逻辑,将View对象存储在convertView
if (convertView == null) {
// throw 一个Exception,包含position,getItemViewType的数据,方便定位
// 或者生成一个默认的View,提供给用户有用的信息——如果的确不至于让app crash的话
}
return convertView;
}
通过上面的方式,如果自己的getView的逻辑返回了null的话,就可以根据堆栈直接定位到错误代码的位置。
注意:getView返回null从java语法上是没问题的,虽然根据约定,它返回null肯定会引发空指针异常——但是这是对调用getView的方法而言。根据堆栈,在页面的ListView显示其childView时,如果getView返回null,
android.widget.AbsListView.obtainView方法就抛出异常。堆栈信息只跟踪到LisView,而不会指向具体的Adapter。
(本文使用Atom编写)
[异常特工]android常见bug跟踪的更多相关文章
- android 常见死机问题--log分析
http://blog.csdn.net/fangchongbory/article/details/7645815 android 常见死机问题--log分析============ ...
- 常见bug解析-移动端
手机测试常见bug解析 1.测试时遇到“手机无响应”? 有以下几个原因: a.手机内存不足 b.android进程之间死锁引起的(就是两个进程之间) c.手机的CPU运行高引起的 可以查看手机的崩溃日 ...
- Android自动化压力测试之Monkey Test Android常见的错误类型及黑白名单的使用方法(四)
Android常见的错误类型有两种 1.ANR类型 1)在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸) 2)BroadcastReceiver在10秒内没有执行完毕 2.Crash类型 1)异 ...
- Android 常见工具类封装
1,MD5工具类: public class MD5Util { public final static String MD5(String s) { char hexDigits[] = { '0' ...
- Android常见开源解决方案
原文:http://m.pstatp.com/group/6348269082899497218/?iid=6036708044&app=news_article&tt_from=mo ...
- Android的BUG(三) - 广为人知的诟病:频繁重启问题
使用过Android的同学,尤其是用过山寨pad,应该对Android的重启问题印象深刻吧.Android由于其设计的复杂性,可能会使得系统在不经意时陷入异常状态,因此Android设计了一套看门狗机 ...
- Android常见漏洞
Android常见漏洞 漏洞名称: Log敏感信息泄露 漏洞描述: 程序运行期间打印了用户的敏感信息,造成泄露 修改建议: 建议禁止隐私信息的log 漏洞名称: web https校验错误忽略漏洞 漏 ...
- 如何在本地搭建一个Android应用crashing跟踪系统-ACRA
https://github.com/bboyfeiyu/android-tech-frontier/tree/master/others/%E5%A6%82%E4%BD%95%E5%9C%A8%E6 ...
- Android常见面试笔试题目
Android常见面试笔试题目 1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢? 答:可以处理消息循环的线程,他是一个拥 ...
随机推荐
- 01.SQLServer性能优化之---水平分库扩展
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 第一次引入文件组的概念:http://www.cnblogs.com/dunitian/ ...
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- 读书笔记:《HTML5开发手册》--HTML5新的结构元素
读书笔记:<HTML5开发手册> (HTML5 Developer's CookBook) 虽然从事前端开发已有很长一段时间,对HTML5标签也有使用,但在语义化上面理解还不够清晰.之前在 ...
- scanf()中清除输入缓冲区的几种方法归纳
应用场景:我们使用多个scanf()的时候,如果输入缓冲区还有数据的话,那么scanf()就不会询问用户输入,而是直接就将输入缓冲区的内容拿出来用了,这就导致了前面的错误影响到后面的内容,为了隔离这种 ...
- .NET Core的日志[4]:将日志写入EventLog
面向Windows的编程人员应该不会对Event Log感到陌生,以至于很多人提到日志,首先想到的就是EventLog.EventLog不仅仅记录了Windows系统自身针对各种事件的日志,我们的应用 ...
- Web APi之认证(Authentication)两种实现方式【二】(十三)
前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...
- [修正] Firemonkey TFrame 存档后,下次载入某些事件连结会消失(但源码还在)
问题:Firemonkey TFrame 存档后,下次载入某些事件连结会消失(但源码还在) 解决:(暂时方法) type TTestFrame = class(TFrame) public const ...
- SNMP简单网络管理协议
声明:以下内容是学习谌玺老师视频整理出来(http://edu.51cto.com/course/course_id-861.html) SNMP(Simple Network Management ...
- Android 指纹认证
安卓指纹认证使用智能手机触摸传感器对用户进行身份验证.Android Marshmallow(棉花糖)提供了一套API,使用户很容易使用触摸传感器.在Android Marshmallow之前访问触摸 ...
- postgresql 基本语法
postgresql数据库创建/修改/删除等写入类代码语法总结: 1,创建库 2,创建/删除表 2.1 创建表 create table myTableName 2.2 如果表不存在则创建表 crea ...