5

Android 你不知道的调试技巧

 1 year ago
source link: http://www.androidchina.net/10550.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Android 你不知道的调试技巧 – Android开发中文站

最新消息:欢迎访问Android开发中文站!商务联系微信:loading_in
你的位置:Android开发中文站 > 热点资讯 > Android 你不知道的调试技巧

本文通过Android Studio工具来讲述你不曾知道的一些Debug小技巧。文中有许多操作,不需要死记硬背,只需浏览一遍,了解一番,增加个印象。等到要上手操作的时候,再忆起本文,回来查看查看。久而久之你就能熟能生巧,成为一代Debug大师!

Android Studio 版本

使用版本为3.5.3

调试的项目只有一张页面,由 RecyclerView + 底部一个Button组成。

使用Logcat查看日志技巧

去除多余信息

为了方便举例,我使用addOnScrollListener(…)方法来监听RecyclerView的滑动事件,然后在onScrolled(…)方法里,通过Log.d(“recycler_view”, “recycler view was Scrolled…”)把信息打印到控制台,如下图所示:

大家可能注意到,上图中有许多内容是我们不需要关心的,例如红圈里面的时间、线程与包名。这时我们可以点击右边工具栏的Logcat Header图标,来把这些信息移除,如:

我们只保留一个TAG,这样我们Logcat界面就会变得清爽很多,看下效果:

在Logcat界面的搜索栏中,我们可以输入自定义的TAG来过滤结果:

但如果存在多个TAG的时候,我们应该把它们保存起来,这样才不仅方便我们回过头来继续查看,也无须在脑中开辟块空间把TAG名记住。来来来,一起动手来编辑一下过滤器配置:

图中左上角的“+”是添加,“-”是移除。

添加完成之后,我们就不用在搜索栏中输入相应的TAG了,取而代之的是,直接点击右上角的过滤器,选择我们添加进去的TAG即可。

为了方便讲解,我在监听中的onScrollStateChanged(…)方法里,使用同一个TAG向控制台打印一条信息:Log.d(“recycler_view”, “state:” + newState),如下图所示:

此时我们只想查看有关它state的值,并不关心其他信息。那么我们可以选中那些多余且不关心的子字符串,右键它,点击Fold lines like this。这样就为我们创建了一个过滤器。
可以折叠所有包含我们选中的子字符串的字符串! 留下我们关心的信息:

现在我们再回过头看看刚才打印出来的这些Log,是不是顿时觉得眼睛轻松了很多!当然点击红圈里面的‘+’,可以随时展开或折叠。

Debug断点跟踪调试技巧

启动Debug有两种方式,一种是点击Debug,即中间的那只小虫子,另一种是点击Attach debugger to Android process,即靠近右边带箭头的小虫子。

一般我推荐使用Attach debugger to Android process来进入调试模式,它能够在App处于运行状态时进入调试模式,而要是通过Debug进入调试,它会停止应用并重启。这样我们还需要一路寻找回我们需要调试的状态,就稍微有点烦心了。

我们点击带箭头的小虫子,弹出Choose Process窗口,选择对应进程,点击‘OK‘按钮,进入调试模式。

现在我们可以在代码中打上断点,打断点的方法就是点击目标行代码行号右侧的空白处,再点击一次就是取消断点,断点是可以上下拖动。

当App在运行时,如果击中了断点,则会在Debug窗口中显示断点信息。

工具栏操作按钮

接着,来了解下Debug的操作按钮:

断点管理区操作按钮:

顺序从上到下:

  • Resume Program:一是可从当前断点移动到下一个断点,断点间的代码自动执行;二是让App从暂停状态恢复到运行状态。
  • Pause Program:暂停App。
  • Stop:对于普通的JAVA项目则是退出调试,对于Android项目则是结束App运行。
  • View Breakpoints:查看所有断点,并可以管理配置断点的行为。
  • Mute Breakpoints:切换启用或禁用所有断点的状态。
  • Get Thread Dump:进入线程Dunmp界面。

调试区操作按钮:

顺序从左往右:

  • Show Excution Point:定位到正在被执行的断点位置。
  • Step Over:单步执行,即前进到下一行代码。
  • Step Into:进入调用方法的第一行,不能跳到类库方法。
  • Force Step Info:与Step Into方法类似,只不过他能跳到类库的方法里。
  • Step Out:前进到当前方法之外的下一行,可与Step Into配合使用。
  • Drop Frame:返回到方法执行的初始点(下方有演示)。
  • Run to Cursor:跳转到光标所在处,需要当前断点已经执行到最后一个,且光标所在的代码行要符合由上到下的执行顺序,不能颠倒。

Drop Frame:可以用来在调试的时候,原本想点击Step Into进入方法内部看看,却不小心点了Step Over向下走了一行。如果调试运行的设备是Android10以上的版本,那么我们可以点击Drop Frame按钮——它的作用是可以把我们从当前方法拉出来,放回方法开始前的地方。接着点击Resume Program按钮,就相当于获取到了一次重新开始的机会!演示如下:

我们把断点打到循环体里的某行代码,想看看循环到某一次时的运行状态。难道此时我们要不停的点Resume Program按钮,直到跳转到满足我们要求的断点吗?

不,当然不需要。假如我们想查看断点在运行到第二十次时的状态,可以右击这个断点,在弹出的窗口中的Condition里加入任何布尔表达式:i==20(可以选择语句的语言),点击‘Done’按钮完成配置:

如果条件为“true”,当代码命中这个条件时,那么就会到达这个断点!

App在运行时击中我们打上的断点,立马会把断点信息显示在在Variables菜单中,然后我们就需要在整个菜单中找出我们想要的信息:

这样有时还蛮麻烦的,我们真正想做的是直接在代码中打上Log,但却不想把Log语句在代码中打得到处都是,这时日志断点就派上用场了!

操作步骤:右击需要打Log的断点,在它弹出的窗口中取消选中Suspend(下面会介绍到),此时窗口会向下展开一些新内容。我们勾选Evaluate and log选项,并在其中添加上Log语句,点击‘Done’按钮。

现在,当线程遇上这个断点的时候并不会停止,它只会计算断点里的Log表达式,并把它记录到控制台,然后继续运行。

想必App在运行的过程中遇到各式各样未知性的异常导致的Crash常常令你抓狂,不过强大的Android Studio提供了异常断点的功能。帮助我们在调试运行的App遇到异常,能够先快速准确的定位到产生异常的地方,而非第一时间停止App的运行。

我们点击断点区工具栏上面的View Breakpoints按钮,呼出断点管理界面。然后点击‘+’,选择Java Exception Breakpoints。如下图所示:

点击后呼出Enter Exception Class界面,我们在搜索栏中填入想要监控异常的关键字。Java代码选择NullPointerException,Kotlin代码选择KotlinNullPointerException,点击‘OK’按钮即可,如下图所示:

不过!!在我模拟空指针异常的时候发现,如果用Java代码写的话,调试器确实能监控的到异常,并能定位产生异常的代码。但是!!我用Kotlin写的话,App直接Crash掉了。并未监控到异常,也没定位到产生异常的代码。

不知道是我调试姿势有问题,还是暂时不支持Kotlin代码。

可以让我们在调试期间,通过更改断点监控到变量的值,来改变App执行的结果!

具体操作如下:

首先我们在获取数据的循环体里打上断点。如下图所示:

通过Debug进入调试模式,在Variables菜单中,选中我们要改变的变量,右击它,在打开的选项中点击Set Value…。如下图所示:

我们把i=1更改为i=28,此时能清楚得看到,在代码中显示的变量i信息也从i:1变成了i:28。如下图所示:

在循环中,原本变量i的值是从1到30,但我们已经把初始i的值改为了28,点击断点区工具栏上的Resume Program按钮,原本需要循环30下才执行完毕的断点现在点3下便可完成。
现在来看看更改变量值后App的情况吧:

Suspend 选项

在我们右击断点的时候,你可能留意到这的Suspend选项,如下图所示:

目前我们“All”与“Thread”之中选择了“All”,意味着在当前执行线程遇到该断点的时候,会停止App内的所有线程,这样就会停止App整个运行状态。

但是如果你正在处理一个多线程App,而你正在寻找一些特别麻烦的异步问题,你可以试着只去暂停那个撞到断点的线程。可把选中“All”改为选中“Thread”。

直到击中某一断点才启用

为了方便举例,我在示例中RecyclerView的滑动监听里面与按钮的点击监听中分别打上断点。

由于断点被打在RecyclerView的滑动监听里,那么我们手指稍微一滑动,就会立即执行该断点。那么在调试的时候我想必须先击中按钮监听里面的断点,才允许执行RecyclerView的滑动监听里面的断点。

此时,Disable until breakpoint is hit功能就派上用场了。

右击RecyclerView的滑动监听里断点,在弹出的窗口里面点击More:

我们就会进入到断点管理界面,在该断点的Disable until breakpoint is hit选项中,禁用断点,直到我们选择的按钮监听里断点被命中为止。如下图所示:

现在手指滑动屏幕的时候并不会触发RecyclerVie滑动监听里面的断点,直到点击了按钮,触发了点击监听里面的断点,才被激活一次。意味着每次执行完该断点,就会被禁用掉,除非再点击一次按钮才被重新激活。演示如下:

当已被打上的断点,我们暂时不需要命中它的时候,我们可以把它给禁用掉,右键断点,在弹出的窗口来取消勾选Enable选择。此时断点会变成一个空心圆。不过更方便的做法是通过“Alt + 点击”,Mac是“Opt + 点击”。这样就能让它在开/关的状态下切换:

有时候我们在执行调试App功能的时候会遇到一些暂时不需要使用的断点,我们又不想把它们删掉,也许调试下个功能可能会用上,所以只能一个一个禁掉它们。

其实,只要我们学会使用断点组,这就方便多了!

右键断点,点击窗口的More,前往断点管理界面。我们还可以点击Debug窗口里的断点区工具栏中的View Breakpoint按钮也能前往。

在该界面中,可以看到所有断点都在上面。我们多选它们,右击,创建一个新的组,你可以把它们起名为你正在处理Bug的名字。

这里我起名为OnScrollListener,意味着该组的断点都来自addOnScrollListener(…)的监听里。如下图所示:

分组完毕后,你可以通过点击组的单选框来切换组内断点开/关的状态。当你处理完Bug后,可以选中组,并点击“-”,即可把它们全部删掉。如下图所示:

Evaluate expression

系统给Variables区的变量对象提供了表达式求值的功能。在抵达断点后,如果有变量对象。我们可以输入任何表达式,来实时查看表达式的计算结果。
首先,可通过点击工具栏上面的Evaluate expression按钮,或者右键目标代码选择Evaluate expression来呼出操作界面。如下图所示:

一般首次打开它的时候,是单行输入模式,我们输入一条textList[position],点击‘Evaluate’按钮,就能在下方Result中浏览对象。如下图所示:

如果我们想输入更加丰富的表达式,那么单行模式不能满足我们的需求。点击输入框的右上角,将单行模式扩展为多行。这样,我们就能够输入更加丰富的表达式:

Evaluate expression 是非常适合充当实时检测器,它能够让我们清楚的观察到当前应用的状态。

分析堆栈轨迹

在合作开发项目中,也许我们会收到来自同事发来的一份包含调用栈的Bug报告,其实也就是一堆文本。我们复制Bug报告,回到Android Studio,点击工具栏上面的Analyze,然后点击Analyze Stack Trace…,我们会发现它找到了粘贴板上面的内容:

点击‘OK’按钮后,它会对我们的调用栈作一个全面的注解,并显示在控制台中。我们点击其中的链接,就会对我们的代码库进行一个快速的检索并定位代码:

本篇文章大部分内容来自谷歌官方的视频Android Studio: 调试的技巧与心得,我推荐大家可以关注下谷歌的官方账号。里面有很多优质的视频,都是由开发者本人来讲解的。

希望本文能给大家在调试App的时候提供多一条思路。

感谢以下资料,让我站在了巨人的肩膀

作者:金灿灿
链接:https://juejin.im/post/5e5345fff265da575a6a0b3e


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK