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

本篇文章主要是针对性在iOS上举行半晶莹剔透模糊效果的支出实现做整理。

Updated on 2016/2/14 更新Stetho 相关,简书markdown不支持锚
-_-||||||||||||
Updated on 2016/1/15
表明谷歌对ADT的摒弃态度,新增段落:对于非发布版本的构建以不同的包名
兵荒马乱时一并创新原文
迎接转载,但要保留译注者链接:http://www.jianshu.com/p/613d28a3c8a0

虽iOS很已经支持使用模糊效果指向图纸等开展拍卖,但越来越当iOS7随后,半晶莹剔透模糊效果得到特别范围广泛使用。包括今年风靡发布之iOS8啊沿袭了立等同统筹,甚至以OS
X 10.10版本Yosemite中吗开始大量用到半晶莹剔透模糊。

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.

于iOS开发中,我们来过多拣好做半晶莹剔透模糊效果,下面就是一对常见的主意还是说工具。

Summary 概要

1. Core Image

当规划及心得方面的首长,苹果好对图纸效果和图处理的支持一定是格外好之,在iOS平台达成,5.0后便应运而生了Core
Image的API。Core Image的API被在CoreImage.framework库中。

当iOS和OS X平台达成,Core Image都提供了大量之滤镜(Filter),这为是Core
Image库中较基本的事物有。按照合法文档记载,在OS
X上起120差不多种Filter,而于iOS上也来90大多。

下面是一律段子Core Image做模糊的示范代码:

 CIContext *context = [CIContext contextWithOptions:nil];
 CIImage *image = [CIImage imageWithContentsOfURL:imageURL];
 CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
 [filter setValue:image forKey:kCIInputImageKey];
 [filter setValue:@2.0f forKey: @"inputRadius"];
 CIImage *result = [filter valueForKey:kCIOutputImageKey];
 CGImageRef outImage = [context createCGImage: result fromRect:[result extent]];
 UIImage * blurImage = [UIImage imageWithCGImage:outImage];

此处可以见见,Core
Image为了做得比灵活,Filter都是准字符串的名去创造的,比如高斯歪曲滤镜就是“CIGaussianBlur”,这里有一个列表可以参照:
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html\#//apple\_ref/doc/filter/ci/CIGaussianBlur

而外这里涉及的多Filter之外,Core
Image还提供了CIDetector等类似,可以支持人口脸识别等,在OS X上Core
Image也召开了重多支持。

运Gradle和它们推荐的色结构

2. GPUImage

而外苹果官方提供的外场,第三着为出应声面图片处理的家伙。一个为Brad
Larson的兄长就整了平等拟叫做GPUImage的开源库。同样的,里面提供了森Filter。

https://github.com/BradLarson/GPUImage

一律是开高斯模糊,用GPUImage可以如此:

 GPUImageGaussianBlurFilter * blurFilter = [[GPUImageGaussianBlurFilter alloc] init];
 blurFilter.blurRadiusInPixels = 2.0;
 UIImage * image = [UIImage imageNamed:@"xxx"];
 UIImage *blurredImage = [blurFilter imageByFilteringImage:image];

至少看起,代码上比较采用Core Image的情事略得几近。

将密码以及灵活数据在gradle.properties中

3. vImage

骨子里,说了上面的Core
Image和GPUImage,很多场面下就曾经够用了。下面我们重来拘禁一个,那即便是vImage。vImage也是苹果推出的仓库,在Accelerate.framework中。

Accelerate这个framework主要是故来做数字信号处理、图像处理相关的向量、矩阵运算的堆栈。我们好当我们的图像都是由于向量或者矩阵数据整合的,Accelerate里既是提供了快速之数学运算API,自然就可知便民我们针对图像做各种各样的处理。

冲vImage我们得依据图像的处理原理直接开模糊效果,或者采用现有的工具。UIImage+ImageEffects是个老好的图像处理库,看名字啊亮堂是本着UIImage做的分类扩展。这个家伙为大面积地采用着。

不用自己写Http客户端,使用Volley或OkHttp

4. 属性及选择

既然已亮了3单章程好半晶莹剔透模糊效果,那么我们如果为此的上理应选哪个也?这是单问题。

  • 自网版本的支撑及来拘禁,这几乎单还多,都是iOS4、iOS5即便支持了底,对于身在iOS8时代的开发者,这点配合已经足够了。
  • Core
    Image是苹果好之图像处理库,本来就是正确,如果苹果自身以某版本做了优化处理,自然又好。主要是为此起比麻烦,还要了解Filter的名。
  • GPUImage来自第三在,但实现开放,用起呢比较简单,在多状况下是出于Core
    Image的选取。
  • 图像模糊处理是很复杂的乘除,最终往往使扣押性。这点及看,我再倾向选择vImage。

每当本人支付之iOS应用被,选择了vImage,出发点是性,这并无是说有那个准确的benchmark。但以几个调剂时的主流机型上测,包括5c、5s等,在模糊半径(blur
radius)达到10横之时,配合动画,vImage的处理时会强烈比紧缺,不见面“卡顿”。

上述是自我对iOS上落实半晶莹剔透模糊效果落实之盘整。

参考:

  • http://boboshone.com/blog/2013/04/22/blur-effect-in-ios/
  • http://nshipster.com/gpuimage/
  • http://blog.denivip.ru/index.php/2013/01/blur-effect-in-ios-applications/?lang=en
  • http://code.tutsplus.com/tutorials/adding-blur-effects-on-ios–cms-21488

转载自:http://www.molotang.com/articles/1921.html

使用Jackson来解析JSON

由于65k方法数限制,避免使Guava并保持数比少之堆栈引用

使用Fragment呈现UI

Activity仅用于管理Fragment

Layout XML同样也是代码,好好组织她

采用style来避免Layout XML中的重属性

行使多只style文件避免大成一个巨大

保障colors.xml简短并谨记DRY,只在中间定义基础色彩

一样保持dimens.xml DRY,仅定义一般常量

决不打了大的ViewGroup层级

免WebView的客户端侧处理,并知道其或许引致内存泄漏

使用Robolectric做单元测试,Robotium做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同时以受Google做吧新专业构建系统积极开发中

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,因为她由Google开发,与Gradle关系最紧密,默认使用新型项目组织,针对Android开发量身定做。

使用 Eclipse
ADT
来展开Android开发不再是一个吓的选择。2015年,谷歌已了针对性ADT的支持,并催促开发者尽快为Android
Studio迁徙。Google ended ADT support at the end of
2015and
urges users tomigrate to Android
Studioas
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。所以Jackson
的体积会比 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 构筑, 如果你要支援可以和她们内部的人头攀谈: Timo Tuominen, Olli
Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera 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。Adapters算是一个麻烦,存在被数和视图之间。然而,典型气象是她会经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的单元测试。然而,Robolectric对于UI
tests是匪完全而错误的。在测试以下相关UI元素时见面来问题:animations,
dialogs,
etc,而且当你“行走于黑暗中”(没法看屏幕正给决定正在操作)时,实际情形到底什么样为是挺难以掌握的。

Robotium
让写 UI tests 变得简单
你也许不欲因此Robotium来连续实机跑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服务如是Google Play Store
and Maps.要是您想使测试三星球特征的APIs,仍旧有必不可少有同等高三星实机。

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,一慢性来自于Facebook
的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)

翻译推荐阅读

  • dex分包
  • 「打造和谐的Library」SharedPreferences篇
  • 行使Chrome来调节你的Android
    App