Android 性能优化:使用 Lint 优化代码、去除多余资源

FelicitasBM 7年前
   <h2>前言</h2>    <p>在保证代码没有功能问题,完成业务开发之余,有追求的程序员还要追求代码的规范、可维护性。</p>    <p>今天,以“成为优秀的程序员”为目标的拭心将和大家一起精益求精,学习使用 Lint 优化我们的代码。</p>    <h2>什么是 Lint</h2>    <p>Lint 是 Android Studio 提供的  <strong>代码扫描分析工具</strong> ,它可以帮助我们发现代码结构/质量问题,同时提供一些解决方案,而且这个过程不需要我们手写 测试 用例。</p>    <p>Lint 发现的每个问题都有描述信息和等级(和测试发现 bug 很相似),我们可以很方便地定位问题,同时按照严重程度进行解决。</p>    <p>当然这个“严重程度”我们可以手动调节,有些原则问题不容侵犯,必须提升到 error,而有的个别问题也可以无视,毕竟人非圣贤孰能无过嘛。</p>    <h2>Lint 工作方式简单介绍</h2>    <p>Lint 会根据预先配置的检测标准检查我们 Android 项目的源文件,发现潜在的 bug 或者可以优化的地方,优化的内容主要包括以下几方面:</p>    <ul>     <li>Correctness:不够完美的编码,比如硬编码、使用过时 API 等</li>     <li>Performance:对性能有影响的编码,比如:静态引用,循环引用等</li>     <li>Internationalization:国际化,直接使用汉字,没有使用资源引用等</li>     <li>Security:不安全的编码,比如在 WebView 中允许使用 JavaScriptInterface 等</li>    </ul>    <p>Lint 检测代码的过程如下图所示:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/e1beb6745233cabba714f107cad78fa4.png"></p>    <ul>     <li><strong>App 源文件</strong> :包括 Java 代码,XML 代码,图标,以及 ProGuard 配置文件等</li>     <li><strong>lint.xml</strong> :Lint 检测的执行标准配置文件,我们可以修改它来允许或者禁止报告一些问题</li>    </ul>    <h2>从命令行运行 Lint</h2>    <p>Lint 的命令很简单:</p>    <pre>  <code class="language-xml">lint [flags] <project directory></code></pre>    <p>Lint 也可以使用 Gradle 运行:</p>    <p>Windows:</p>    <pre>  <code class="language-xml">gradlew lint</code></pre>    <p>Mac:</p>    <pre>  <code class="language-xml">./gradlew lint</code></pre>    <p>具体命令行相关的操作这里就不介绍了,因为这个过程实在太痛苦,上一张命令行运行 Lint 后得到的 XML 文件截图让你体验一下:</p>    <p><img src="https://simg.open-open.com/show/f63d58532393f63ade29fda7b456a4a7.jpg"></p>    <p>我们还是直接进入 Lint 的 GUI 操作吧。</p>    <h2>Android Studio 中使用 Lint</h2>    <p>Android Studio 中内置了 Lint,我们小手一点就可以直接使用。</p>    <p>Lint 的使用路径:</p>    <p>工具栏 -> Analyze -> Inspect Code…</p>    <p>点击 <strong>Inspect Code</strong> 后会弹出检查范围的对话框:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/4c51d72f39ed4329375d34fd9c242d87.jpg"></p>    <p>默认是检查整个项目,我们可以点击 <strong>Custom scope</strong> 自定义检查范围。</p>    <p>点击右边的下拉框,会出现以下选择:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6fedf21540e7ffc3e5da3a39e0c103c2.jpg"></p>    <p>分别有:</p>    <ul>     <li>Project Files:所有项目文件</li>     <li>Project Production Files:项目的代码文件</li>     <li>Project Test Files:项目的测试文件</li>     <li>OpenFiles:当前打开的文件</li>     <li>Module ‘app’:主要的 app 模块</li>     <li>Current File:当前文件</li>    </ul>    <p>除了内置的选项我们还可以自己选择特定的类进行检查,点击下图中的红色框部分:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/df4e3ccb01563f7d9e9f5fbf313285bf.jpg"></p>    <p>会弹出自定义范围选择框,默认是空的,我们可以点击左上角的“+”号新增一个检查范围:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6618506319f3851d8ad341e59073b0f0.jpg"></p>    <p>-  <strong>Local</strong> :只能当前项目使用</p>    <p>-  <strong>Shared</strong> :其他 Android Studio 项目也可以使用</p>    <p>我们选择 Shared,然后起个帅气的名字 “ShixinCuteLint”,默认按项目显示,这时检查的文件数为 0 :</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7b1873d11505e9ec26e2d2f841b6e16e.jpg"></p>    <p>上图中右边的四个按钮表示要操作的类型:</p>    <ul>     <li><strong>Include</strong> :包括当前文件夹内的文件,但不包括他的子文件夹</li>     <li><strong>Include Recursively</strong> :包括当前文件夹以及它的子文件夹内所有的文件夹,递归添加</li>     <li><strong>Exclude</strong> :移除当前文件夹,不包括子文件夹</li>     <li><strong>Exclude Recursively</strong> :移除当前文件夹及所有子文件夹</li>    </ul>    <p>我们点击左边的 app 文件夹后,点击右边的 Include Recursively 按钮,把 app 下的所有文件添加到检查列表:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/607602626697cf0f0812cbdb451aa5ed.png"></p>    <p>可以看到,这时 app 下的文件都变绿了,总共有 689 个文件夹要扫描。</p>    <p>点击 OK 进行检测,稍等一会儿,会弹出 Inspection 对话框,显示检查结果,没想到我的代码居然有 1769 个警告!这数字触目惊心啊:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/2c46696f8f8b7a2c62006599d3587e88.jpg"></p>    <p>我们主要关注红框内的警告,先来看看我的代码 Performance 有什么问题:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a6ae2292919d9b2b7ab9e188ab52d566.jpg"></p>    <p>哈哈,没想到我还有这么多进步空间!</p>    <p>上图可以看到,Lint 真是神器,可以帮我们发现自己忽略或者没有意识到的问题,尤其是性能方面,如果你觉得自己代码想优化又不知道从何做起,不妨让 Lint 给你指指路。</p>    <h2>团队中建立代码规范利器:提升、降低问题的等级</h2>    <p>虽然 Lint 可以帮我们检查代码的问题,但多人合作时,我们更期望可以在写代码时就发现问题、解决问题。</p>    <p>鉴于团队成员中水平良莠不齐,靠个人意识有时候很难保证质量,这时可以修改 Lint 对于特定问题的警告等级,以最直观的 IDE 提示来警醒成员。</p>    <p>Lint 的警告严重程度有以下几种:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ce87f3a8c36eacab4ec9c907a9814f15.jpg"></p>    <ul>     <li>Unused Entry:没有使用的属性,灰色,很不起眼</li>     <li>Typo:拼写错误,绿色波浪下划线,也不太起眼</li>     <li>Server Problem:服务器错误?好像不是</li>     <li>Info:注释文档,绿色,比较显眼</li>     <li>Weak Warning:比较弱的警告,提示比较弱</li>     <li>Warning:警告,略微显眼一点</li>     <li>Error:错误,最显眼的一个</li>    </ul>    <p>日常开发中,好一点的程序员会关注 Warning 的警告,根据警告优化代码,但那也只是很少一部分。但是红色的 Error 就不一样了,基本上看到就想要消灭掉。</p>    <p>我们拿命名拼写错误举个例子。</p>    <p>类、对象、遍历拼写错误看起来不是什么问题,但是如果你见过大量的无意义或者错误命名,你一定会赞同我的接下来做法。</p>    <p>默认的拼写错误是 Typo ,提示很弱,所以常被人忽略:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f0d7cd55ed240cc894c2bbc6cb7f3f6a.jpg"></p>    <p>上面的 String 类型变量 login 写成了 logn,Lint 默认对拼写错误是个下滑波浪线,很不起眼。我们修改一下。</p>    <p>打开 Preferences/Settings,搜索 Inspections,会出现 Lint 的检测配置页面:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/66cfd718a59aadd12b2fb8ab89f7cf23.jpg"></p>    <p>要修改拼写的警告等级,搜索“spelling”:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fc3a7e594216a6896505f92b7cfdffa4.jpg"></p>    <p>然后选择出现的 Typo,再点击右边的 Severity 就是严重程度,改成 Error,OK。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ff610ade2b1c157d1140159637142d72.jpg"></p>    <p>可以看到,现在拼写错误就会出现红色的错误警告了,让你不好好写变量名!</p>    <h2>Lint 虽好,也不能贪杯。</h2>    <p>Lint 就像是一个洁癖患者,虽然可以让我们代码干净许多,但是如果真要把它提示的全解决,恐怕老板要发怒了:给你发工资天天玩电脑,怎么不出活呢?!</p>    <p>Lint 报的某些警告的确是没必要,这时我们可以选择忽略这些警告。忽略警告可以分两种:</p>    <ol>     <li>在 Java 代码中</li>     <li>在 XML 文件夹中</li>    </ol>    <h3>在 Java 代码中忽略 Lint 警告:</h3>    <p>忽略 Lint 警告的注解跟 @SuppressWarnings 很类似,@SuppressLint(“忽略的警告名称”)。</p>    <p>下面的代码演示了如何忽略 Lint 对使用新 API 的警告:</p>    <pre>  <code class="language-xml">@SuppressLint("NewApi")  @Override  public void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.main);  }</code></pre>    <p>要是你不清楚要忽略的警告具体是什么名字,那就直接忽略 all,当然是当前类/方法/对象:</p>    <pre>  <code class="language-xml">@SuppressLint("all")</code></pre>    <h3>在 XML代码中忽略 Lint 警告:</h3>    <p>只需两步:</p>    <ol>     <li>xml 中声明 tools 命名空间</li>     <li>使用 tools:ignore=”忽略的警告名”</li>    </ol>    <p>例如:</p>    <pre>  <code class="language-xml"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"                xmlns:tools="http://schemas.android.com/tools"                tools:ignore="all"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:orientation="vertical"                android:background="@color/white"></code></pre>    <h2>Gradle 中配置 Lint</h2>    <p>Gradle 中也可以配置 Lint 的关键操作,比如是否开启 Lint 警告,或者关闭指定的警告。</p>    <p>在 module 下的 build.gradle 中添加 lintOptions{…}, 样例代码如下:</p>    <pre>  <code class="language-xml">android {    ...    lintOptions {      // Turns off checks for the issue IDs you specify.      disable 'TypographyFractions','TypographyQuotes'      // Turns on checks for the issue IDs you specify. These checks are in      // addition to the default lint checks.      enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'      // To enable checks for only a subset of issue IDs and ignore all others,      // list the issue IDs with the 'check' property instead. This property overrides      // any issue IDs you enable or disable using the properties above.      check 'NewApi', 'InlinedApi'      // If set to true, turns off analysis progress reporting by lint.      quiet true      // if set to true (default), stops the build if errors are found.      abortOnError false      // if true, only report errors.      ignoreWarnings true    }  }  ...</code></pre>    <h2>自动删除查找出来的无用资源文件</h2>    <p>代码迭代版本一多,很容易会遗留一些无用的代码、资源文件,我们可以使用 Lint 进行清除。</p>    <p>点击 Android Studio 工具栏 -> Analyze -> Run Inspection By Name..,输入要检测的内容,这里是无用资源:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/39897f520c0f47e6d462141ff6e0137f.jpg"></p>    <p>然后选择 Unused resources,再选择范围后就开始检测。</p>    <p>检测出这么多无用文件:</p>    <p><img src="https://simg.open-open.com/show/c873bc1a1bdb1ea9cb5b8b2e00f8e7c8.jpg"></p>    <p>注意,右边有解决方法: <strong>Remove All Unused Resources</strong> ,放个大图显眼一点:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/23ec505dccabed217321aa08fe1c7c7d.jpg"></p>    <p>点击后,boom ,从此世界清静了。</p>    <p>Lint 是优秀程序员之友,吾日三省吾身,今日 Lint 了没?!</p>    <p> </p>    <p> </p>    <p>来自:http://www.androidchina.net/6257.html</p>    <p> </p>