Android 如何快速的定位错误和解决错误,如何去编码

本篇文章主要分为五章,分别讲解如何编码、熟悉别人代码、定位和解决bug、常见bug产生后的效果和如何提升个人效率。每一章我将会从【预期效果,不可预期效果,事件驱动,逻辑驱动,代码驱动】五个方面让读者去理解和掌握本章的知识和经验。

先解释一下我提到的几个概念:

预期效果:当一个业务(逻辑)流程开始完整结束,这个流程所需合理数据和不合理数据的校验,直到流程最终成功或者失败。

不可预期效果:当一个业务流程在符合校验数据下执行的过程中,用户突然打断该流程执行的情况。

事件驱动:用户在使用app产品的时候必须去触摸手机屏幕或者通过语音、传感器等去通知软件执行操作,这种通知我称为一个事件。

逻辑驱动:每一个业务从开始到结束都会有一个过程,这个过程描述了先做什么,在做什么,以及最后做什么,我把这个过程的全部细节称为一个逻辑。

代码驱动:在开发语言中,在某个线程中,每一行代码或者每一次代码调用从微观上讲都是线性的,也就是按顺序执行的。这种顺序的执行我称为代码驱使。

明白了这些概念可能有助于理解代码的执行和逻辑的执行,更容易去编码和定位漏洞,接下来将分别详细阐述。

第一章:如何编码

纵观我过去Android所有写过的代码,我总结了一下总共包括以下几个方面:

1、自定义UI控件

2、UI布局的编写

3、UI控件的事件监听、UI的控制

4、数据校验逻辑代码编写

5、系统功能的调用

6、第三方SDK、库的使用

7、网络请求的代码编写

8、数据的本地持久化操作

9、性能优化和屏幕适配

详细步骤:

第一步:弄清楚功能流程,和非功能流程

第二步:弄清楚是,非功能流程驱动功能性流程驱动功能还是,功能驱动非功能流程。

第三步:在UI方面一定要考虑默认字体,背景,颜色,大小,屏幕适配等等,一定要将默认的具体化,否则不同的手机将会展示不同的效果

第四步:编码过程中,一定要考虑某个对象获取成功,和失败,不能只考虑成功的流程,要对不成功的流程要做很多的校验。

第五步:考虑到对于流程进行中不可改的对象禁用。

第六步:对于耗时操作,一定要考虑,微观上的线性执行,并在主线程中对,子线程获得的数据进行校验和线性逻辑融合。

第七步:具体自己体会,代码一定是按流程按事件的。

注意:所有代码编写,最好符合:①代码驱动②逻辑驱动③事件驱动,这样写出来的代码更健壮,也不会被系统回收,解决bug也将变得更加简单。

第二章:如何快速熟悉别人的代码

原则:①事件驱动②逻辑驱动③代码驱动

详细步骤:

第一步:当拿到别人的代码时,不要着急去看代码,要先运行,看看都有哪些功能。只有熟悉有哪些功能我们才能去根据业务去熟悉代码,而且功能的流程就是代码的执行流程。

第二步:如果是Android studio项目应该去看build.grade中的dependencies标签,看看项目中用到哪些框架和相关组件,这些组件都是做什么的。

或者


另外,看看项目的libs下有什么jar包等等,这样就能熟悉项目使用的第三方的功能。

如果是eclipse项目,直接去看libs下的jar包即可。

第三步,使用Android studio,按照界面上的特殊关键词进行搜索,即按Ctrl+shift+f(不起作用可能与显卡或输入法冲突)进行搜索,然后根据驼峰命名法,见名思意找到相关布局文件和对应的activity文件。


第四步:最后根据activity的生命周期执行顺序,结合我们的思想, ①事件驱动②逻辑驱动③代码驱动,根据触发的事件,去看一个完整流程。

注意:当要修改某个功能也是一样,要问清楚那个界面,那个控件,按照该思想,你将很快找到对应的文件,如果代码是我们编码的思想,那我们将更容易找到,而且代码健壮性更好。

最后:当你要找某个类中某个控件或者变量,请选择局部搜索,或者使用


第三章:如何快速定位bug和解决bug

原则:①事件驱动②逻辑驱动③代码驱动

思想:①不慌不忙①详细观察、询问、重现bug,清楚那个界面,那个控件,那种事件

思路:第一步:解决bug最难的就是定位bug,当别人提出一个bug时,你要问清楚,那个界面,触发了什么事件,导致了什么样的问题,是错误还是预期效果达不到。

第二步:当你弄清楚这些,就安装app进行问题重现,然后看日志输出。


若果日志中,有自己写的代码、方法、类,直接点击即可定位到该问题的代码。

看看方法调用栈:


因此,抛异常的最先出栈,也就是最先输出,及在日志中是最上面的代码。所以只需要定位到哪行代码,根据所发现的问题进行解决。如图


注意:对于,预期结果达不到的,一定要结合熟悉代码的理论去找bug,因为通过特殊关键词,你就能快速定位bug所在类。达不到预期结果的不会产生错误日志,所以不能去看异常日志,要采用debug方式,或者打日志的方式,后面有详细例子。

最后呢,所有问题不能单独看某一个,要结合日志,debug,打log的,注释,等方式结合。具体问题具体对待,选择最优的调试方式,不断改进。

第四章:常见bug产生的效果有什么不同

1、运行时异常(空指针为例)

空指针是每个程序员遇到次数最多的异常,相信大家都被困扰过。

空指针效果:模拟器会弹出程序已停止的提示框,真机会直接闪退。也就是说,当遇见软件闪退,就有很大一部分是空指针。而空指针只有三种情况:

① 省略对象指针this,调用继承的方法。

② 获得系统的对象,调用系统的方法。

③ 用自己编写类的对象,调用类中的方法。

这三种情况,我们在调试中都能看到系统输出的异常日志,因此看这类些空指针也是有技巧的。

经验:第①类,空指针肯定是由传入参数无法语法检查,导致系统无法识别(即就是括号内参数存在错误),需要修改对应参数。

第②类,空指针肯定是由于,只声明没有初始化造成的。(即就是“.”前面为空)。

第③类,空指针情况比较特殊看日志,就要先检查“.”前面对象是否创建,再检查参数是否合适。

因此、在检查错误时,一定要先看日志,确定异常所在位置是系统代码还是自己代码,然后上述情况解决。

例如:

如图第①类空指针,日志及错误,该错误指向了setContentView(),因为是继承关系,省略了this,因此这类异常肯定是参数,而我们参数是个布局文件id,而对应的布局是xml,不会进行语法分析只会校验标签对应关系,就算你是小写也不错报错,因此遇见这个问题应该用如下步骤去检查。第一,检查标签是否正确,第二,采用注释法,注掉一部分进行调试确定范围,直到明确到某个标签。

 

例如第②类情况如下,当你去掉tv的获取,会产生空指针。而当你直接调用系统方法,里面传null是不会产生空指针的。


第③类,不举例说明,结合①和②即可。

2、数据异常(预期效果达不到)

数据异常一般不会导致app直接奔溃,而是达不到预期的效果。这种异常多见于并发或异步较多,为了更好的用户体验,Android更注重异步操作,因此、才规定activity中不能执行耗时操作,必须放在子线程中执行,通过消息机制交互,更新UI必须在主线程中。这点也是最不好找的错误,因为从思想上很难理解、比如网络框架之类的都是区分主线程和子线程的。

解决这类问题:一定要从两方面进行,因为异步的过程,所以,一定要考虑异步的操作是失败的还是成功的。另外不管是成功还是失败都要处理相应的逻辑。

具体解决步骤:

最好的办法就是通过打日志,就是利用代码驱动的思想。其次,使用debug,但是debug有问题。

打日志技巧①在开始异步之前打一条②成功中打一条③失败中打一条④如果自己写的异步在异步代码中也打一条日志。例如:

 debug调试这种错误一般会对你产生误导,因为debug当遇到异步或者无法进入的代码时,会停留在当前方法中的任意一行或者直接停留在该方法的最后一个大括号上,所以对于没有经验的人来说,你认为执行的是那条代码,其实不然是因为,没法debug造成的。

例如:下图哪行代码并未执行,但却停在了哪里

3、没有日志

对于不打日志的,很少见,解决办法就是利用编程思想,在对应代码加上try-catch语句或者换用模拟器。如果还不行,那就只能采用别的代码方式,这种是应为jdk不支持或者屏蔽了内部日志,你可以采用强制日志输出。很难举例子,具体情况可以分享。

第五章:如何快速的提升个人效率

1、积累工具类代码,一定要积累编程中遇到的工具类和比较通用的代码和,例如找个文件夹存放等:


2、记录过去遇到的问题,没事总结一下自己是怎么解决的,可以写笔记之类的,当再次遇到,做到可查。