「译」Android最佳实践指南——GitHub Star 7000+

Updated on 2016/2/14 更新Stetho 相关,简书markdown不帮忙锚
-_-||||||||||||
Updated on 2016/1/15
注解谷歌(谷歌)对ADT的屏弃态度,新增段落:对于非揭橥版本的营造利用差其余包名
不定时手拉手更新原文
迎接转发,但请保留译注者链接:http://www.jianshu.com/p/613d28a3c8a0

Lessons learned from Android developers in
Futurice. Avoid
reinventing the wheel by following these guidelines. If you are
interested in iOS or Windows Phone development, be sure to check also
our iOS Good
Practices

and Windows App Development Best
Practices

documents.

Summary 概要

动用Gradle和它推荐的种类社团

将密码和机智数据放在gradle.properties中

决不自个儿写Http客户端,使用Volley或OkHttp

使用Jackson来解析JSON

由于65k方法数限制,防止使用Guava并保持数量较少的库引用

使用Fragment呈现UI

Activity仅用于管理Fragment

Layout XML同样也是代码,好好社团它们

运用style来防止Layout XML中的重复属性

动用八个style文件幸免生成一个极大

有限支撑colors.xml简短并谨记DRY,只在其间定义基础色彩

一如既往保持dimens.xml DRY,仅定义一般常量

绝不创造过深的ViewGroup层级

幸免WebView的客户端侧处理,并精通它大概引致内存泄漏

利用罗布olectric做单元测试,罗布otium做UI测试

模拟器使用Genymotion

再而三利用 ProGuard 或 DexGuard

简易的数额持久化使用SharedPreferences,其余的使用ContentProvider

利用Stetho进行应用debug


Android SDK

Android
SDK

放在您的home目录或是其余使用非亲非故的职位。某些IDE安装的时候就带有了SDK,并且会将其放置在与IDE相同的目录下。当你要求进步(或重装,或转移)IDE时那就成了一件坏事。同时还要防止将SDK放在另一个连串级其余目录下,那样很大概会让你在使用user权限运行IDE时需求用到sudo权限。

Build system 营造连串

你的默许选项相应是
Gradle。Ant的范围要多而且语句还更没完没了。使用Gradle,可以简单落成:

  • 使用不一致的flavours或variants来创设你的app
  • 制作简便的script-like的tasks
  • 管理并下载倚重
  • 自定义keystores
  • 还有越多

Android’s Gradle plugin同时在被谷歌做为新规范创设系统积极开发中

Project structure 项目组织

有二种普遍利用的取舍:旧式的Ant & Eclipse ADT project
structure,和新颖的Gradle & Android Studio project
structure。你应该选拔新型,就算你还在行使旧式,考虑将之做为宝贵遗产并转载新式吧。

Old structure:

old-structure
├─ assets
├─ libs
├─ res
├─ src
│  └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro

New structure:

new-structure
├─ library-foobar
├─ app
│  ├─ libs
│  ├─ src
│  │  ├─ androidTest
│  │  │  └─ java
│  │  │     └─ com/futurice/project
│  │  └─ main
│  │     ├─ java
│  │     │  └─ com/futurice/project
│  │     ├─ res
│  │     └─ AndroidManifest.xml
│  ├─ build.gradle
│  └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle

第一不相同点在于新式使用了来自Gradle的定义,更清楚地分开了’source sets’
(main, androidTest)。举个例子,你可以添加source sets ‘paid’ 和
‘free’ 到 src中作为打造 paid 版本 和 free 版本的代码目录。
利用一个top-level app对此将您的app从那么些需求引用的 库项目 (e.g.,
library-foobar) 中区分开来很得力。settings.gradle中写着那一个能被app/build.gradle引用的 库项目 的引用。

Gradle configuration Gradle配置

General structure. Follow Google’s guide on Gradle for
Android

Small tasks. 与那一个 (shell, Python, Perl, etc)
脚本分裂,你能用Gradle来配置tasks。Just follow Gradle’s
documentation

for more details.

Passwords.
在app的
build.gradle中你须求为release版本的打造定义signingConfigs,以下为索要防止的事项:

毫不那样做。这一个信息会产出在版本控制系统中。

signingConfigs {
    release {
        storeFile file("myapp.keystore")
        storePassword "password123"
        keyAlias "thekey"
        keyPassword "password789"
    }
}

与之相应,通过一个不会带有在版本控制系统中的gradle.properties这样做:

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

本条文件将会被gradle自动载入,所以你能在build.gradle中像那样来行使它:

signingConfigs {
    release {
        try {
            storeFile file("myapp.keystore")
            storePassword KEYSTORE_PASSWORD
            keyAlias "thekey"
            keyPassword KEY_PASSWORD
        }
        catch (ex) {
            throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
        }
    }
}

**选取 Maven 化解正视而非导入 jar **
一旦你肯定地在品种中蕴藏特定版本的 jar(比如说 2.1.1),下载与拍卖
jars 的换代将会是一件笨重累赘的事,这几个难点在 Maven
中被化解得很好,那也是 Android Gradle builds
所鼓励的艺术。看下边那几个事例:

dependencies {
    compile 'com.squareup.okhttp:okhttp:2.2.0'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
}

防止 Maven 的动态倚重
避免选择动态器重的库版本, 像是 2.1.+
,因为那说不定会招致差其他、不安定的打造,或是在多次创设之间表现出微薄的、不可追踪的距离行为。使用静态版本像是2.1.1会创建更安宁的、可预料的和可另行的开支条件。

对此非揭橥版本的打造利用不一样的包名
debugbuild
type
运用applicationIdSuffix
,那可以让debug还有release本子的apk同时安装在同一部配备上(固然您有别的要求的话,仍可以将此技术运用于自定义的
build 类型)。对于一个 app
的生命周期来说,当它被揭橥到市场将来,这一特征将变得越发有价值。

android {
    buildTypes {
        debug {
            applicationIdSuffix '.debug'
            versionNameSuffix '-DEBUG'
        }

        release {
            // ...
        }
    }
}

使用差距的icons来分别安装在装置上的不比营造版本app——比如说使用不一致的情调或是使用一个覆盖的”debug”标签。对于Gradle来说,那卓殊不难,你只要求将debugicon
放在app/src/debug/res,而release icon 放在
app/src/release/res。你仍可以针对差别的创设版本更改应用名change app
name
,versionName也可以变更(就好像上边那些事例做的那样)。

IDEs and text editors IDE和文件编辑器

无论是使用什么编辑器,它必须能针对项目结构令人热情洋溢地利用
文件编辑器是一个很个人的接纳,按照项目协会和打造系统来让编辑器起到作用同时也是你的权责。

此时此刻最推荐的IDE是 Android
Studio
,因为它由谷歌开发,与Gradle关系最严密,默许使用新型项目布局,针对Android开发量身定做。

使用 Eclipse
ADT

来进展Android开发不再是一个好的挑三拣四。二〇一五年,谷歌(谷歌(Google))截止了对ADT的支撑,并催促开发者尽快向Android
Studio迁徙。Google ended ADT support at the end of
2015
and
urges users tomigrate to Android
Studio
as
soon as
possible.你也足以一连使用它,不过急需一番安顿,因为它采取旧式项目社团与Ant打造。固然Eclipse 的 Gradle 集成令你利用得不快活,你的取舍唯有应用命令行来构建。

你也能只利用一个仅仅的文书编辑器像是Vim,Sublime Text, 或
Emacs。在那种气象下,你要求在指令行环境下选拔 Gradle 和 adb

甭管你利用什么,总得确保使用 Gradle 和流行项目布局
来营造利用,注意不要将编辑器相关的配置文件加到版本控制系统中。比如,幸免添加Ant
build.xml 文件。
若是您在 Ant 中改变配置, 一定毫无忘记让build.gradle保持 up-to-date 和
functioning 。

还有,善待其他的开发者,不要强求他们转移她们天性化的工具配置。

Libraries 库

Jackson
是一个用来 Object 与 JSON
间相互转换的Java库。Gson
也是一个当作化解此难点广受欢迎的留存。但是我们发现 Jackson表现更好,因为它提供了可拔取的方法来处理 JSON : streaming, in-memory
tree model, and traditional JSON-POJO data binding。所以杰克逊的体积会比 GSON 要大。取决于你的莫过于景况,你大概匡助于采取 GSON 避防止65k 方法数限制。其余选项还有:
Json-smart
and Boon
JSON

互联网,缓存和图像.
那时候有一些种经过实战检验的用于后端服务器请求的缓解方案,你将运用哪种取决于你协调快要完毕的客户端。使用
Volley

Retrofit.
Volley 额外提供了 helpers 以搞定 载入和缓存图像。假如你挑选
Retrofit, 考虑用
Picasso
来做那几个, 同时用
OkHttp
来完结高效 HTTP 请求。Retrofit, Picasso 和 OkHttp
那多少个工具由同样家合营社支出,所以她们能全面地补足相互。 OkHttp can also
be used in connection with
Volley
.

RxJava 是一个响应式编程框架,换句话说,处理异步事件。
它是一种强大并有前途的范例,大概从可读性上讲不是那么美丽因为它是如此的不同。大家推荐你在采纳那个库来修建整个应用之前抱持着丰硕的当心。有一部分连串经过应用
RxJava 构筑, 假设你须求支持可以和她们内部的人攀谈: 提姆o Tuominen, Olli
Salonen, Andre Medeiros, 马克 Voit, Antti Lammi, 维拉 Izrailit, Juha
Ristolainen. 我们写了有些博文发表在那方面:
[1],
[2],
[3],
[4].

如果你过去从未有过行使 Rx 的经历,只需求从将它看作对 API
的答问伊始即可。你也足以选择从作为简单 UI 事件处理起始,像是 search
field 上的点击或然输入事件。假若您对友好的 Rx
技能丰裕自信并操纵将它使用到总体应用构筑中,一定要对准所有科学驾驭的片段写Javadoc。用心记住其余不熟识Rx
的程序员或许会对保安项目感到无比头大。尽你的奋力来援助她们知晓您的代码还有
Rx 。

Retrolambda
是一个用来让 JDK8 从前的 Android
或是其余平台支撑Lambda表明式语法的库。它用于维持您的代码紧凑并可读,越发是当你拔取函数式风格编写代码比如说
RxJava 。为了利用它, 你须求设置 JDK8, 在 Android Studio 的 Project
Structure dialog 设置它当做你的 SDK Location , 然后装置条件变量
JAVA8_HOMEJAVA7_HOME , 接着在项目根目录的 build.gradle 引用倚重:

dependencies {
    classpath 'me.tatarka:gradle-retrolambda:2.4.1'
}

并在每个模块的 build.gradle 中添加

apply plugin: 'retrolambda'

android {
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

retrolambda {
    jdk System.getenv("JAVA8_HOME")
    oldJdk System.getenv("JAVA7_HOME")
    javaVersion JavaVersion.VERSION_1_7
}

Android Studio 提供了对于 Java8 lambda 的代码协理匡助,假若你是 lambda
的新手,只需从以下指出中伊始:

  • 其他只有一个艺术的接口都是 “lambda friendly”
    的,亦即能被裁减成更连贯的语法格式
  • 假设对 参数 或任何 的如何拿不准,那么就写一个平常的匿名内部类并让
    Android Studio 为你将它收缩成 lambda 格式

注意 dex 方法数限制,避免采纳过多库
Android apps 当被打包成 dex file 时, 有一个恒定的引用方法数限制:65536
[1]
[2]
[3].
要是你超出了这一范围,就会在编译时相遇一个沉重错误。出于那几个理由,使用尽大概少的库,并且动用那几个工具
dex-method-counts
来决定利用什么库集合来保障低于这一范围。更加要避免使用 Guava library,
因为它含有当先 13k 方法.

Activities and Fragments

本着如何最佳地因此 Fragments 和 Activities 来社团 Android
架构尚无统一结论,那点不论在社区仍然在 Futurice
的开发者中都是如出一辙。Square
甚至开发了一个库用来最大化地由此View来建造应用架构 a library for
building architectures mostly with
Views
,以此绕过对于
Fragment 的倚重性,但那在社区中仍未被看做大规模推介的方案。

出于Android
API的历史,你能自然地想到将Fragments作为屏幕上的UI碎片。换句话说,Fragments常常与UI相关联。Activities能被自然地想到作为控制器,从生命周期和状态管理上的根本来说。可是,你很恐怕遇见角色爆发变化的事态:activities或许被当做UI角色(delivering
transitions between
screens
),而fragments能被单独作为控制器
fragments might be used solely as
controllers
。大家引进谨慎启航,获知尽只怕多的信息然后作出决定,因为无论选用fragments-only、activities-only依旧views-only架构,都设有着其缺点。那里对于急需小心些什么有一部分指出,但你须要持保留态度吸收它们:

  • 避免大规模应用嵌套fragments nested
    fragments

    , 那大概会时有发生 matryoshka
    bugs

    。 要么在有含义的时候使用嵌套fragments (举个例子, 在一个screen-like
    的fragment中要求一些 fragments 放在一个水平方向滑动的 ViewPager 中)
    ,要么就确保那是一个三思而后行后的主宰。
  • 防止放太多代码在activities中。任何动静下如果恐怕,让它们作为轻量containers,其设有意义紧要在于运用的生命周期循环以及其他重大的Android-interfacing
    APIs。选取单fragment的activity而不是一个可是的activity,那样可以将UI代码放在fragment中。当你必要变更它以重新放置到一个标签布局或是一个多fragment表格屏幕中去的时候,那使得它亦可被复用。防止所有一个无对应fragment的activity,除非你一点一滴驾驭那样做的结局。
  • 决不让您的应用的里边工作滥用Android-level
    APIs,像是重度倚重于Intent。那可能会潜移默化到Android
    OS或是其余使用,创建bugs或许延缓。举个例子,假使您的运用使用Intent作为内部通信手段,只怕会促成多秒延迟——若是它在OS启动后随着被用户打开的话。

Java packages architecture Java分包架构

在Java分包架构方面,Android只好算是粗略接近MVC模型Model-View-Controller。在Android中,Fragment和Activity是事实上的操纵器类Fragment
and Activity are actually controller
classes
。从一头来说,它们又肯定是用户接口的局地,所以还要也是视图。

出于这一理由,不可以将fragments (or
activities)严俊划分为控制器或是视图。让它们保持团结的fragments
package更好一些。Activities能放在最高级package中只要你按照此前部分的提议。如若您安顿超越几个或八个Activities,那么再加一个
activities package。

此外,也得以像经典的MVC这样来开展分包架构,通过利用一个models
package包罗POJOs(那么些POJOs由JSON解析器解析API
responses转化生成),和一个views
package包括你的自定义Views,notifications, action bar views, widgets,
etc。艾达pters算是一个劳顿,存在于数据和视图之间。然则,典型气象是它们会通过getView()主意输出一些视图,因而你可以把adapters
subpackage将在views里面。

局地application-wide的和接近于Android系统的操纵器类能够停放在一个managers
package中。混杂的数量处理类,像是”DateUtils”,放在utils
package中。这个用来与后端交互的类则放在network package中。

由此看来,体系是从 closest-to-backend 到 closest-to-the-user:

com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
   ├─ adapters
   ├─ actionbar
   ├─ widgets
   └─ notifications

Resources 资源

命名 听从类型前缀惯例,像是 type_foo_bar.xml. Examples:
fragment_contact_details.xml, view_primary_button.xml,
activity_main.xml.

组织 layout XMLs. 要是你不确定什么格式化 layout XML,
以下惯例会有着支持:

  • 一个性子一行,4 空格缩进
  • android:id 总是作为第三个性情
  • android:layout_**** 这类属性放在最下边
  • style 属性放在最上面
  • Tag closer /> 拥有自个儿的一行, 以使顺序清晰和添加属性变得不难
  • 与其应用硬编码 android:text, 不如考虑拔取规划时属性 Designtime
    attributes

    ,其受 Android Studio支持.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="@string/name"
        style="@style/FancyText"
        />

    <include layout="@layout/reusable_part" />

</LinearLayout>

用作一个经验法则,android:layout_****应当在layout
XML中定义,同时其余的习性android:****应当放在style
XML中。那条法则会有不一样,但总体而言工作得很好。这些想法是为了仅将layout
(positioning, margin, sizing)和content属性放在layout files中,而外观详情
(colors, padding, font) 放在 styles files中。

那么些例外是:

  • android:id 分明应该放在 layout files 中
  • android:orientation 属性对于 LinearLayout 来说一般 放在 layout
    files 中更有意义
  • android:text 应该置身 layout files 中因为它定义了 content
  • 有点景况下让 style 来定义 android:layout_width
    android:layout_height 常量会很有用,但默许境况下它们应该出现在
    layout files 中

使用 styles. 大约各种品类都急需得体地拔取 style,因为对此 view
来说具有重复的外观是尤其广泛的事,看上面这几个例子:

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

该 style 被用于 TextViews:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

你很可能须求为buttons做一些平等的事,不要在此间停下。从微观角度上提炼出一组相关联的、重复的android:****属性到一个共用的
style 中去。

把一个大的 style 文件分割成两个
您不要拘泥于单个 styles.xml 文件。 Android SDK
援助其他不合乎这一命名规则的文书,关于文件名
styles怎么着魔法也从未,起效果的是文本中的 XML tags <style>
。因而你能拥有那样命名的style文件 styles.xml, styles_home.xml,
styles_item_details.xml, styles_forms.xml。 不像 resource
目录那样命名对创设系统有着意义, res/values
目录下的文书命名完全可以私自。
注:是的,你可以在strings.xml中放color资源,ResourceManager通过炫耀能够找到它。

colors.xml 是一个颜色调色板
你的colors.xml中永不放其余东西,只须求映射颜色名到一个RGBA值。不要为不一致品种的buttons定义RGBA值。

Don’t do this:

<resources>
    <color name="button_foreground">#FFFFFF</color>
    <color name="button_background">#2A91BD</color>
    <color name="comment_background_inactive">#5F5F5F</color>
    <color name="comment_background_active">#939393</color>
    <color name="comment_foreground">#FFFFFF</color>
    <color name="comment_foreground_important">#FF9D2F</color>
    ...
    <color name="comment_shadow">#323232</color>

你只是简单地应用重新RGBA值来格式化,但那会使得在需求变更基础颜色的时候变得操作复杂。同时,那一个概念与上下文紧凑关联,像是”button”
or “comment”,它们应该放置于一个button style 中,而非colors.xml

Instead, do this:

<resources>

    <!-- grayscale -->
    <color name="white"     >#FFFFFF</color>
    <color name="gray_light">#DBDBDB</color>
    <color name="gray"      >#939393</color>
    <color name="gray_dark" >#5F5F5F</color>
    <color name="black"     >#323232</color>

    <!-- basic colors -->
    <color name="green">#27D34D</color>
    <color name="blue">#2A91BD</color>
    <color name="orange">#FF9D2F</color>
    <color name="red">#FF432F</color>

</resources>

向利用设计者询问调色板。命名无须全都是颜色名像是”green”, “blue”,
etc.那样的命名也是全然可以接受的:”brand_primary”, “brand_secondary”,
“brand_negative”。像那样格式化颜色会让改变和重定义颜色变得简单,还是可以令人收看一共有些许种不一致的颜料被采取。寻常对优质的UI设计来说,减弱所采纳颜色的多种性是一件主要的事。

出色对待 dimens.xml ,正如对待
colors.xml.
您也应当定义典型的距离和字号大小的“调色板”,像对于情调的中坚打算那样。一个好的
dimens 文件的例证像是这样:

<resources>

    <!-- font sizes -->
    <dimen name="font_larger">22sp</dimen>
    <dimen name="font_large">18sp</dimen>
    <dimen name="font_normal">15sp</dimen>
    <dimen name="font_small">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_huge">40dp</dimen>
    <dimen name="spacing_large">24dp</dimen>
    <dimen name="spacing_normal">14dp</dimen>
    <dimen name="spacing_small">10dp</dimen>
    <dimen name="spacing_tiny">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_tall">60dp</dimen>
    <dimen name="button_height_normal">40dp</dimen>
    <dimen name="button_height_short">32dp</dimen>

</resources>

像一般比较strings那样,你应有利用spacing_**** dimensions 来安装
layouting, margins 和
paddings,而不是选取硬编码值。那会带来一样的观感,同时让组织和转移styles及layouts变得简单。

strings.xml

利用类似的命名空间来定名你的strings的keys,不要惧怕在多个或两个keys中重复某一个值。语言是很复杂的,所以命名空间是有必不可少的,它能用于提供上下文新闻还有打破模糊。

Bad

<string name="network_error">Network error</string>
<string name="call_failed">Call failed</string>
<string name="map_failed">Map loading failed</string>

Good

<string name="error.message.network">Network error</string>
<string name="error.message.call">Call failed</string>
<string name="error.message.map">Map loading failed</string>

永不写全大写的string值。遵从一般的公文惯例(e.g., capitalize first
character)。假使您必要将整句string大写彰显,那么针对实例使用TextView中的那么些个性textAllCaps

Bad

<string name="error.message.call">CALL FAILED</string>

Good

<string name="error.message.call">Call failed</string>

幸免深层级的 views.
有时候你只是想要再加一个LinearLayout,用于达成部分views的安放。但那种状态却只怕会生出:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <RelativeLayout
        ...
        >

        <LinearLayout
            ...
            >

            <LinearLayout
                ...
                >

                <LinearLayout
                    ...
                    >
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

尽管你未曾在layout文件中一向目击到这般的气象,但那最终有或许爆发,假如你填充(in
Java) views到其它views中。

部分标题可能会生出。你或然遇见过质量问题,因为那样会生成一棵复杂的UI树来让电脑解析。另一个更要紧的标题则是只怕带来栈溢出荒谬:
StackOverflowError.

为此,试着让您的views层级尽只怕的扁平:学习怎么着使用RelativeLayout,
怎么着优化你的布局 optimize your
layouts

还有何样行使 <merge>
tag
.

清楚与 WebView 相关的难点
当你无法不要出示一个web页面的时候,比如说一篇小说,防止客户端侧的对于HTML的清理处理,更好的方法是从后端程序中直接获得一段
纯粹的” HTML
。当有着Activity的引用而非ApplicationContext时,WebView还恐怕引致内存泄漏WebViews
can also leak
memory

when they keep a reference to their Activity, instead of being bound to
the ApplicationContext。幸免用 WebView 来做一些简单的文件或按钮,
更好的挑选是 TextViews 或 Buttons。

Test frameworks 测试框架

Android SDK’s testing framework尚不完善,更加是关于于UI 测试。Android
Gradle完成了一个命名为connectedAndroidTest的测试任务,它能运作你创制的JUnit
test,参考extension of JUnit with helpers for
Android
.那象征你必要连接实机或模拟器来运转测试,参考官方测试的指南[1]
[2]

使用 Robolectric
作为 unit tests, 而并非做 views tests

那是一个转业于狠抓支付速度的不用连接装置的测试框架,更加适用于针对models
和 view models的单元测试。然则,罗布olectric对于UI
tests是不完全并且错误的。在测试以下相关UI成分时会有难题:animations,
dialogs,
etc,而且当你“行走于漆黑中”(没办法看到屏幕正被操纵着操作)时,实际情况终究如何也是可怜麻烦了解的。

Robotium
让写 UI tests 变得不难
你或然不须求用罗布otium来连接实机跑UI
case,但您仍会经过它获得利益,因为它提供了多如牛毛helpers用于获取及分析views以及控制显示屏。Test
cases 将看起来很不难像是那样:

solo.sendKey(Solo.MENU);
solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
solo.clickOnText("Preferences");
solo.clickOnText("Edit File Extensions");
Assert.assertTrue(solo.searchText("rtf"));

Emulators 模拟器

即使您是专业的Android apps开发者,买一个正经版 Genymotion
emulator
呢。Genymotion比原生模拟器运行起来有着更高的帧速。它具有一些工具用于调试你的利用,像是模拟互连网连接品质,GPS地点等。用于连接着开展UI
test它也很了不起。你仍是可以赢得许多(不是任何)差其余虚拟设备,与购入许多实机比较Genymotion专业版的开销实在是充裕有利于。

警示:Genymotion emulators不帮忙具备的谷歌服务像是谷歌(Google) Play Store
and Maps.借使您想要测试三星(Samsung)特色的APIs,如故有须要拥有一台三星(Samsung)实机。

Proguard configuration Proguard配置

ProGuard
常作为Android项目中核减体积、混淆代码的工具。

是否接纳ProGuard取决于你的花色配置。平日你可以在gradle中像那样安插以在创设规范apk时行使ProGuard。

buildTypes {
    debug {
        minifyEnabled false
    }
    release {
        signingConfig signingConfigs.release
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

为了操纵某些代码是急需保持原样依然甩掉(注:即未实际拔取,不打包,那也就是为何使用ProGuard会减弱使用体积)仍然混淆,你需求在代码中提出一个或五个关键点。那几个首要点区分出这么些典型的类:with
main methods, applets, midlets, activities, etc.
Android
framework使用的默许混淆配置能在此地找到:SDK_HOME/tools/proguard/proguard-android.txt,使用那几个布局,再添加你自身在那边定义的系列范围的配备:my-project/app/proguard-rules.pro,将会联手构成最后的ProGuard混淆规则。

应用ProGuard平常遇到的一个题材是使用启动时闪退,错误音讯则为ClassNotFoundException
or NoSuchFieldException or similar,就算运行创设命令成功 (i.e.
assembleRelease) 且无警告。
那代表以下一到两件事:

  1. ProGuard移除了类、枚举、方法、域或声明,检查一下哪些是不须要移除的局地。
  2. ProGuard混淆(重命名)了类、枚举、域,但这一个都在代码中被一直动用了它们原来的命名,
    i.e. through Java reflection.

检查app/build/outputs/proguard/release/usage.txt看是否有疑虑对象被移除掉了。
检查 app/build/outputs/proguard/release/mapping.txt
看是还是不是有狐疑对象被歪曲了。

防止ProGuard放弃一些亟需的类或类成员,在你的ProGuard配置中插足keep
options:

-keep class com.futurice.project.MyClass { *; }

预防ProGuard混淆一些内需的类或类成员,添加keepnames:

-keepnames class com.futurice.project.MyClass { *; }

Check this template’s ProGuard
config

for some examples.
Read more at
Proguard
for examples.

尽快地在你的档次中提供一个正规版本营造
用来检查ProGuard是或不是推行不利符合预期是尤其重点的事。当你引用了新库的时候,记得营造一个正规
版本在实机上测试一下。不要等到你的行使要揭破”1.0″版本了再来打造标准版本,你可能会碰着一些令人不心情舒畅的大悲大喜,而你未曾剩余的光阴去匡正它们。

建议 保存好每个您发布给你用户的正儿八经版本的mapping.txt file
。通过所有这个文件,你才可以debug一些标题,当你的用户遇见bug并交由了一份包涵混淆的stack
trace.

DexGuard. 如要你要求一个 hard-core tools 来优化并混淆正式版本代码,
可以考虑
DexGuard,
制作 ProGuard 的团体推出的商用软件. 它还是可以自在地划分 Dex files
以化解65k办法数限制.

Data storage 数据存储

SharedPreferences

固然你只需持久化不难的标志位并且你的应用只在单进度环境下运行。SharedPreferences对你的话很或许早就丰硕了。它是正确的默许选项。

那时有三个原因会让你不想要使用SharedPreferences:

  • 性能: 你所有大批量数额依然数额自个儿至极复杂
  • 多进程获取数据:
    你有所运行在独家进程中的组件或是远程服务,它们需求联合数据

ContentProviders

在SharedPreferences不够满足你的须要的动静下,你应该运用作为平台标准的ContentProvider,它高效并且经过安全。

至于ContentProvider的题材则在于你在使用它前边须要写大量的楷模似的代码,还有就是低品质的学习指南。假诺大概的话,使用机关库来生成ContentProvider,那样会明确滑坡劳力。such
as
Schematic.

你照旧必要靠你本身来写一些分析代码用于从Sqlite列中读取出Object数据,反之亦然。你可以系列化数据对象,像是使用Gson,并且只具有结果字串。通过那种办法你会损失一些性情,但一边你将不需求为数据类中的逐个域都表明列。

Using an ORM

俺们普通不引进应用对象关系映射库Object-Relation Mapping
library,除非你持有不平时的错综复杂数据和亟待化解的需求。它们趋向复杂并需要时刻去上学。即便您说了算拔取ORM了,如果你的使用对
进度安全 process safe 有需求的话就要小心所接纳的库是或不是帮衬这一表征,许多现存的ORM解决方案让人诧异地不帮衬。

Use Stetho

Stetho,一款来自于非死不可的Android applications debug bridge,与Chrome
开发者工具集成在共同。使用它你很自由就能检查选择,越发是互连网通讯。它还是可以让你简单地反省和编辑SQLite
数据库、shared preferences。然而,你利用确保Stetho
仅在debug版本中可用,release版本中不可用。

Thanks to

Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera
Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and
other Futurice developers for sharing their knowledge on Android
development.

License

Futurice Oy
Creative Commons Attribution 4.0 International (CC BY 4.0)

翻译推荐阅读

相关文章