摘要:通过工具对Android项目源码进行质量检测

从开发的角度来讲,一款软件的优秀与否,除了与软件整体架构有关,还决定于开发者的编码是否规范以及能否对相关平台特性的充分利用。对于软件的整体架构,目前阶段我们只能依靠开发者的经验,去构建良好的架构。对于编码是否规范以及平台特性的使用,除了开发者的编码经验,我们还可以依赖一些工具来对我们编写的源码进行检查,来提高代码的质量。本文将以Android为平台,对三种代码质量检查的工具进行介绍。

一、Android SDK中自带的StrictMode(限制模式)

最新的Android平台中(Android 2.3起),新增加了一个类,叫StrictMode(android.os.StrictMode),这个类可以用来帮助开发者改进他们编写的应用,并且提供了多种策略,这些策略能及时的检查应用中存在的问题。

我们可以在项目的开发测试阶段,将项目ProjectBuild Target改为Android2.3或2.3以上,使用系统提供的StrictMode(限制模式)来进行开发测试,并使用 StrictMode给我们提供的多种限制策略,进行单个线程,或者整个jvm的监测,例如,我们通过使用ThreadStrictMode对磁盘读写和网络进行检测,当程序运行过相关的代码后,我们就可以得到所有读写磁盘和访问网络所消耗的时间,进而是我们得知项目当中哪些地方耗时过长,我们就可以在那些不合理的地方进行优化。

StrictMode还给我们提供了多种形式的策略违背输出,例如log日志,运行时弹出对话框等模式。StrictMode的使用也是非常简单。例如,你想对UI线程中的读磁盘进行检测,你只需要在主线程当中Activity的onCreate方法加入以下代码即可:

StrictMode.setThreadPolicy((newStrictMode.ThreadPolicy.Builder()).detectDiskReads().penaltyLog().penaltyDialog().build());

当有读取磁盘的时候便会在log中输出以下内容(并且会在正在运行的模拟器或手机上弹出对话框,提示当前程序有策略违背):

10:03:56.122: DEBUG/StrictMode(16210): StrictMode policy violation; ~duration=696 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=23 violation=2

同样,当对Activity对象进行检测,Activty对象内存泄漏的时候,便会在log当中输出如下内容:

05-17 09:45:24.835: E/StrictMode(566): class com.alipay.StrictModeDemoActivity;instances=2; limit=1

05-17 09:45:24.835: E/StrictMode(566):android.os.StrictMode$InstanceCountViolation: classcom.alipay.StrictModeDemoActivity; instances=2; limit=1

目前,StrictMode给我们提供了两大类的策略,一类是对于当前线程的监控(Disk Reads、Network access等),另外一类是关于VM虚拟机等方面的监控策略(内存泄漏的Activity对象和SQLite对象)。

但通过项目实践,发现如果想通过StrictMode来保证代码的质量,是远远不够的,一是StrictMode检测到策略违背时输出的log日志包含的信息是有限的,二是现在给我们提供的检测策略种类还不够多。但是值得欣慰的是,从API Level10到15,我发现Google也在不断的完善StrictMode这个工具类,相信在不久的将来它的作用一定会越来越重要。

二、ADT自带的Lint工具

在Eclipse的ADT插件更新到最新的16.0及以上版本,内部集成了一个名为Lint的工具。Lint工具能够专门针对Android工程项目进行全面的分析,包括项目内的资源文件、布局文件和静态代码进行检查,检查结果如下图:

下面列举一些项目检查过程中发现的典型问题:

1)代码中的字符串没有进行全球化处理。

提示信息: "AboutVersionName" is not translated in en

2) 不同命名的两个图片文件,具有相同的图片内容,资源冗余。

提示信息:The following unrelated icon files have identical contents: alipay_contact_normal.9.png, alipay_qrcode_normal.9.png

3)xml布局文件或描述文件当中的一些比较典型的警告信息

提示信息:The id "AlipaySubTitle" is not referring to any views in this layout

提示信息:<uses-sdk> tag appears after <application> tag

4)布局文件的优化

提示信息:This <Framelayout> can be replaced with a <merge> tag

5)代码的高效性

用Android API中性能更好的SparseArray来代替HashMap。

Use new SparseArray<String>(...) instead for better performance

6)低性能的源代码:

mBackImgMap.put("0",new Integer(R.drawable.basic));

优化之后的源代码:

mBackImgMap.put("0",Integer.valueOf(R.drawable.basic));

最好不要直接调用包装类的构造函数,而用valueOf方法来替代他,这样有助于程序更高效的执行。

提示信息:Use Integer.valueOf(R.drawable.basic) instead

7)避免在manifest.xml文件中对debug属性进行硬编码,

提示信息:Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one

美中不足的是eclipse插件形式的Lint工具还没有导出错误报告的功能。

三、JAVA代码质量检测工具PMD

最后一个介绍的工具是PMD,相对于前两种代码质量检测工具,它不是专门给android编程定制的工具,PMD最大的优势在于它能够依据java通用的编码规范检测出代码当中编码不规范的地方,在通用的编码过程中,它的作用明显要比前两种工具更广泛,而且检查更加严格。

首先在自己的电脑中安装PMD工具(我安装的是eclipse的PMD插件,推荐大家以这种方式来安装,用起来更加傻瓜式一些,当然专家级的朋友可以安装PMD的独立客户端,详细资料请参考http://pmd.sourceforge.net/rules/java/strictexception.html)。

下面结合当前项目中的部分实际代码来进行对PMD工具的实践:

在eclipse中选中当前项目,点击右键->PMD -> check code with PMD

就会在项目源码中加入不规范的提示信息,我们也可以以报告的形式导出这些不规范的编码列表,当然导出报告的形式有多种,如下图reports文件夹:

下面结合代码当中的一些不规范代码来进行具体说明:

1)sourceCode:packagecom.alipay.android.appHall;

problem: src/com/alipay/android/appHall/AppHall.java:1        Package name contains upper casecharacters

包的命名需要用小写字母。

2)sourceCode:

public void onItemClick(AdapterView<?>parent, View arg1, int index, long arg3) {

AppItemInfo itemInfo = mAppItemInfos.get(index);

itemInfo.onClick(mContext);

}

problem: src/com/alipay/android/appHall/AppHall.java:43      Local variable 'itemInfo' could bedeclared final

局部变量itemInfo可以声明为final。

3)sourceCode:

public static intgetDensityDpi(Context context) {

DisplayMetrics displayMetrics = getDisplayMetrics(context);

returndisplayMetrics.densityDpi;

}

problem:src/com/alipay/android/appHall/Helper.java:176       Parameter'context' is not assigned and could be declared final

因为参数context没有在方法内做任何改动,参数类型可以声明为final。

4)sourceCode:

catch (Exception e){}

problem:src/com/alipay/android/appHall/Helper.java:290       Avoidempty catch blocks

捕获异常后没有做任何处理。

5)Helper类的getConfigInfo()方法,非常复杂

problem:src/com/alipay/android/appHall/Helper.java:317       Themethod 'getConfigInfo' has a Cyclomatic Complexity of 17.

getConfigInfo()方法过于复杂,PMD工具明确规定了方法和类的复杂度,当超过时就会报出警告信息。(PMD对于一个类的方法和属性的数量也做了明确的规定,一个类的方法或者属性过多都会被警告)

6)sourceCode: ArrayList<UIInterface>mdelayGetValueGroup=new ArrayList<UIInterface>();

problem:src/com/alipay/android/appHall/NormalPage.java:53       Avoid using implementation types like 'ArrayList'; use theinterface instead

用抽象的接口来代替具体的类。

7) sourceCode:

if (resultCode == Activity.RESULT_OK){

if (appRunTime.doServiceCallback(null))

return;

}

problem:src/com/alipay/android/appHall/NormalPageFrame.java:114   These nested if statements could be combined

两次if判断可以合并成一个来处理,更加简洁。

8) sourceCode:int index =snapshotQrCode.indexOf(":");

problem:src/com/alipay/android/appHall/NormalPageFrame.java:168   String.indexOf(char) is faster than String.indexOf(String).

用字符类型的参数比用字符串类型的参数更加高效。

9) sourceCode: System.out.println("REQUEST_CODE_QRCODEaccount=......");

problem:src/com/alipay/android/appHall/NormalPageFrame.java:174   System.out.print is used

程序中用到了控制台输出语句,大量的输出语句如果在发布的版本中执行,会极大的影响软件的运行效率,通过PMD我们可以定位源码中所有用到的输出语句,并将其清除。

10)sourceCode:

if (runTimeTimerMap ==null ||runTimeTimerMap.size()== 0) {

return;

}

problem:src/com/alipay/android/appHall/NormalPageFrame.java:351    Substitute calls to size() == 0 (or size() != 0) with calls toisEmpty()

isEmpty()方法比 size() == 0 (or size() != 0)更加高效。

11)另外,在代码质量的分析过程中,发现有大量的地方应该用final关键字,代码中都没有使用,几乎在一半以上的类中都多次出现了这个问题,以下两种情况出现的最多,在这里稍微总结下:

a.当方法当中声明的字段内容在初始化后不会再进行修改,便可以在声明这个字段的时候加上final关键字。

b.当类中一个成员变量的初始化,只需在这个成员变量声明的时候或者在这个类的构造函数内初始化的时候,这个成员变量可以在声明的时候加上final关键字。

四、小结

以上介绍的三种java代码检测方法各有特点,StrictMode是一种轻量级的代码检测方式,对于磁盘的读写、联网以及Activity对象的内存泄漏等几种比较严重的错误进行检测。Android开发工具当中自带的Lint工具更加专业,能够针对Android项目当中的冗余资源文件进行扫描(第一次扫描项目时竟然检测出了大约80K冗余图片资源),布局文件当中的不合理地方进行提醒,还能根据Android SDK的特性对于项目当中的静态代码进行检查,提示出Android平台特有的更佳高效的实现方式。而PMD工具更加侧重于以业内标准的JAVA编码规范对项目内的静态JAVA代码进行检查,而且检查的力度更加严格,更具有规范性。

但无论以上的哪一种方式,都不是完美的,用以上的几种方法进行代码质量检查,从检测结果中我们可以看到,最终的问题报告都包含了大量的编码问题,我们需要对这些报告的结果进行人工帅选,把那些有价值的问题进行研究并在项目中加以修正,这才是最最重要的一个环节。

备注:如果大家有更好的代码检测工具或者方法,可以给我留言,也可以发我邮箱qian.zqzq@alipay.com,我会及时的更新与大家一起分享。

Android项目源码质量检测相关推荐

  1. 173个Android项目源码及下载地址

    173个Android项目源码及下载地址 注:最近一直没有上CSDN,看到不少想学Android的朋友们想要这几个Android项目源码,所以我把它上传到了CSDN,希望能在Android的学习路上对 ...

  2. android生成车票动效,Android项目源码功能齐全的12306火车票订票系统项目

    [实例简介] 本项目是一个基于安卓的12306火车票客户端项目源码,实现了早期的登录注册购票改签等功能.但是因为12306网站改版比换鞋垫还频繁,所以功能早就不能用了,不过项目提供了大部分功能的原来实 ...

  3. 健身android源码,Android项目源码运动健身项目

    [实例简介] 本项目是健身项目Android应用,本软件包含健身项目和计时运动,更多的了解运动前和运动后需要注意的事项和禁忌,也包含了许多健康的健身习惯的文档,应该说这个应用太强大了,用到技术,项目中 ...

  4. 音乐播放器类的Android项目源码

    收集了很多音乐播放器类的Android项目源码,非常不错的开源项目,会让你事半功倍,希望大家补充...谢谢! Android基于经纬度切歌的冲绳音乐播放器源码 http://neast.cn/foru ...

  5. android 快传 源码_安卓APP仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端...

    适用范围:安卓APP仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端 演示地址:(以截图为准) 运行环境:Android+PC+web 其他说明: 本项目是一个基于安卓的类似茄子 ...

  6. Android项目源码分享

    ├─android web应用 │      jqmDemo_static.zip │      jqmMobileDemo-master.zip │      jqmMobileDemo1_1-ma ...

  7. 173个Android项目源码

    http://www.ctdisk.com/file/11774106 365MobileSecretary v1.0.6(365手机助手AIDL) 888个经典 Logo.rar 2012-10-1 ...

  8. 网上的很多Android项目源码有用吗?Android开发注意的地方。

    在Android项目开发中,我们可以在网上看到很多项目源码,大部分也不是很精致, 比如 06.Android阿福多媒体播放器开发教程+源码 还有什么浏览器源码. 那么这些有用吗?  价值在哪里? 精致 ...

  9. android项目源码

    Android开发又将带来新一轮热潮,很多开发者都投入到这个浪潮中去了,创造了许许多多相当优秀的应用.其中也有许许多多的开发者提供了应用开源项目,贡献出他们的智慧和创造力.学习开源代码是掌握技术的一个 ...

最新文章

  1. linux下远程控制继电器,更智能的电脑远程开关机-基于继电器
  2. 为何python不好找工作k-给急着找工作的人一些建议,别在被骗了!
  3. 利用:header匹配所有标题做目录
  4. 20150901-Linux磁盘管理及文件系统管理
  5. 【原理图操作】原理图更新PCB时未改动元器件布局变动问题?
  6. Unity3D_(游戏)卡牌03_选关界面
  7. Python中多线程thread与threading的实现方法
  8. easymock使用方法_EasyMock最终方法– PowerMock,JUnit 4,TestNG
  9. python列表用什么符号表示_python列表类型
  10. word另存为PDF时Mathtype公式显示不全的问题
  11. 图片复印如何去除黑底_如何去除扫描件的底色? 扫描的图片去除背面的阴影的方法...
  12. Sina weibo新浪微博 API返回信息详解
  13. 《计算机网络技术》第一章课后习题答案(全)
  14. uniapp上高德(百度)地图API的使用(APP安卓)
  15. 赋值具有的非单一 rhs 维度多于非单一下标数错误的分析和解决方法
  16. adb升级版命令大全
  17. LINUX系统编程__文件编程__LINUX库open等函数的应用
  18. git入门(msysgit图文安装)
  19. java greenfoot_Greenfoot下载
  20. Cameralink转SDI接口转换器 产品模块

热门文章

  1. 写一写虎扑APP首页效果,jrs都进来看一眼!
  2. 百度官方文档Plus版,PaddlePaddle深度学习框架介绍
  3. Office如何设置主题颜色/主题色
  4. C# 提取Excel形状中的文本和图片
  5. win32API函数
  6. 何为LDO(low dropout regulator)
  7. 容器Docker的介绍与使用
  8. c# mysql 插入返回id_在C#中,mysql插入一条数据时,怎么同时把这条数据的主键返回?...
  9. [国产PLC]耐特品质PLC在全自动定位圆瓶贴标机中怎么运用
  10. rust中文补丁steam_腐蚀rust游戏界面设置中文翻译图介文绍