| dialog_title | 弹出框标题 |
| button_ok | 确认键 |
| loading | 加载文字 |
colors.xml
colors.xml的name命名使用下划线命名法,在你的colors.xml文件中应该只是映射颜色的名称一个ARGB值,而没有其它的。
不要使用它为不同的按钮来定义ARGB值。
不要这样做
<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>
使用这种格式,你会非常容易的开始重复定义ARGB值,这使如果需要改变基本色变的很复杂。
同时,这些定义是跟一些环境关联起来的,如button,应该放到一个按钮风格中,而不是在colors.xml文件中。
相反,这样做
<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>
像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。
通常一个具有审美价值的UI来说,减少使用颜色的种类是非常重要的。
注意:如果某些颜色和主题有关,那就单独写一个colors_theme.xml
。
dimens.xml
像对待colors.xml一样对待dimens.xml文件,dimens命名应该按照一套统一的规则。 一个好的例子:
<resources\>
<!--?font?sizes?-->
<dimen?name\="font_22"\>22sp</dimen\>
<dimen?name\="font_18"\>18sp</dimen\>
<dimen?name\="font_15"\>15sp</dimen\>
<dimen?name\="font_12"\>12sp</dimen\>
<!--?typical?spacing?between?two?views?-->
<dimen?name\="spacing_40"\>40dp</dimen\>
<dimen?name\="spacing_24"\>24dp</dimen\>
<dimen?name\="spacing_14"\>14dp</dimen\>
<dimen?name\="spacing_10"\>10dp</dimen\>
<dimen?name\="spacing_4"\>4dp</dimen\>
<!--?typical?sizes?of?views?-->
<dimen?name\="button_height_60"\>60dp</dimen\>
<dimen?name\="button_height_40"\>40dp</dimen\>
<dimen?name\="button_height_32"\>32dp</dimen\>
</resources\>
布局时需要尺寸大小时进行引用,像这样规范的尺寸很容易修改或重构,会使应用所有用到的尺寸一目了然,会使组织和改变风格或布局是非常容易。
styles.xml
style的name命名使用大驼峰命名法。几乎每个项目都需要适当的使用style文件,因为对于一个视图来说有一个重复的外观是很常见的。
将所有的外观细节属性(colors、padding、font)放在style文件中。 在应用中对于大多数文本内容,最起码你应该有一个通用的style文件,例如:
<style name="ContentText">
<item name="android:textSize">@dimen/font_normal</item>
<item name="android:textColor">@color/basic_black</item>
</style>
应用到TextView中:
`<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/price"
style="@style/ContentText"`
/>
需要为控件做重复的事情时,可以将重复的属性放到通用的style中。
Android代码规范之代码样式规范
==================
Android开发代码样式(format)一般按照Google默认提供的格式:
可以在settings设置中去修改,但一般我们不做修改,统一用默认的样式即可。除非有特殊要求。
一些需要注意的:
1. 大括号
大括号与if, else, for, do, while语句一起使用,即使只有一条语句(或是空),也应该把大括号写上。
2. 非空块:K & R 风格
对于非空块和块状结构,大括号遵循 Kernighan 和 Ritchie 风格 (Egyptian brackets):
-
左大括号前不换行
-
左大括号后换行
-
右大括号前换行
- 如果右大括号是一个语句、函数体或类的终止,则右大括号后换行; 否则不换行。
例如,如果右大括号后面是else或逗号,则不换行。
示例:
new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
}
}
};
3.一行一个语句
每个语句后要换行。
4.块缩进:4个空格
每当开始一个新的块,缩进增加4个空格,当块结束时,缩进返回先前的缩进级别。缩进级别适用于代码和注释。
最好使用4个空格代替Tab,在不同的编译环境中,Tab所表示的长度可能不一致。
5.自动换行
术语说明:一般情况下,一行长代码为了避免超出列限制(80或100个字符)而被分为多行,我们称之为自动换行(line-wrapping)。
我们并没有全面,确定性的准则来决定在每一种情况下如何自动换行。很多时候,对于同一段代码会有好几种有效的自动换行方式。
从哪里断开:
自动换行的基本准则是:更倾向于在更高的语法级别处断开。
-
如果在非赋值运算符处断开,那么在该符号前断开(比如+,它将位于下一行)。
-
这条规则也适用于以下"类运算符"符号:点分隔符(.),类型界限中的 &(),catch 块中的catch符号。
-
如果在赋值运算符处断开,通常的做法是在该符号后断开(比如=,它与前面的内容留在同一行)。
-
方法名或构造函数名与左括号留在同一行。
- 逗号(,)与其前面的内容留在同一行。
6.空行
以下情况需要使用一个空行:
-
类内连续的成员之间:字段,构造函数,方法,嵌套类,静态初始化块,实例初始化块。 例外: 两个连续字段之间的空行是可选的,用于字段的空行主要用来对字段进行逻辑分组。
-
在函数体内,语句的逻辑分组间使用空行。
- 多个连续的空行是允许的,但没有必要这样做(我们也不鼓励这样做)。
7.空格
以下情况需要使用一个空格:
-
分隔任何保留字与紧随其后的左括号(()(如if, for catch等)。
-
分隔任何保留字与其前面的右大括号(})(如else, catch)。
- 在任何左大括号前({),两个例外:
o @SomeAnnotation({a, b})(不使用空格)。
o String[][] x = foo;(大括号间没有空格)。
- 在任何二元或三元运算符的两侧。这也适用于以下"类运算符"符号:
o 类型界限中的&()。
o catch块中的管道符号(catch (FooException | BarException e)。
o foreach语句中的分号。
-
在, : ;及右括号())后
-
如果在一条语句后做注释,则双斜杠(//)两边都要空格。这里可以允许多个空格,但没有必要。
-
类型和变量之间:List list。
- 数组初始化中,大括号内的空格是可选的,即new int[] {5, 6}和new int[] { 5, 6 }都是可以的。
8.每次只声明一个变量
不要推荐使用组合声明,比如int a, b;。如非必须,变量在需要的时候才去声明并初始化。
9.方法参数不宜过多
如果方法参数太多,函数声明方法名会很长,可以考虑用实体类来封装参数。
10.方法中的行数不宜过多
如果方法长度没有统一标准规定,因为有的方法确实会很长,但是一般来说当方法长度超过50行左右,可以考虑优化进行方法提取(refactor)。
例如最常见的在Activity的onCreate方法中写过长的代码:
不要这样做
相反,这样做
是不是简洁清晰了很多
Android代码规范之代码注释
================
好的代码需要一套规范的注释方法
1) 一个工程应有一个统一的头文件注释,以说明整个工程的信息、创建日期、版本等等
2) 对重要的程序必须加注释进行说明
3) 修改代码或删除时,将原代码用注释的方法屏蔽,同时要加开发者自身对修改操作的注释
4) 移除所有临时或无关的注释,以避免在日后的维护工作中产生混乱
5) 注释应对代码进行准确的说明,不应存在歧义
1. 类注释
原则上编写完成每个类都要有一个头部注释,标注类的功能描述,作者,联系方式和修改日期等。对自己的代码负责。
头部注释的添加有两种方式:
第一种方式,可以在AS中,Settings → Editor → File and Code Templates → Includes → File Header,输入:
/**
* 描述:添加类的描述
* @anthor $(USER)
* @e-mail XXX@XX.com
* @time? ?${DATE}
*/
这样便可在每次新建类的时候自动加上该头注释。
第二种方式,在Settings → Editor → Live Templates中配置,
详情参考:[http://www.cnblogs.com/zgz345/p/4994885.html]( )
[http://blog.csdn.net/pkandroid/article/details/52686199]( )
这种方式是配置模板和对应的快捷键,比如我的配置完成后在类的开头输入lf回车就会自动生成对应的注释模板:
?
??
相比第一种而言,不会每个类新建都生成,只有需要的时候再手动添加,更加灵活。
2. 方法注释
原则上每一个成员方法(包括自定义成员方法、覆盖方法、属性方法)的方法头都必须做方法头注释。
在方法前一行输入/** + 回车或者设置Fix doc comment(Settings → Keymap → Fix doc ?comment)快捷键,
AS便会帮你生成模板,我们只需要补全参数即可:
3. 块注释
块注释是最常用的注释,它与其周围的代码在同一缩进级别。
它们可以是/* ... */风格,也可以是// ...风格(//后最好带一个空格)。
对于多行的/* ... */注释,后续行必须从*开始, 并且与前一行的*对齐。
一般我们还会注释掉代码,修改代码或删除时,将原代码用注释的方法屏蔽,同时要加开发者自身对修改操作的注释。
3. TODO注释
当你需要后续再对代码进行补充修改时,可以使用todo模板注释, 在代码中输入todo、fixme等这些注释模板,然后回车,
AS会自动帮你生成如下注释:
要查找之前哪些todo没有完成,可以在AS左下角todo面板中很方便的找到,AS会将你所有的todo项列出:
喜欢这个功能的可以看看这篇文章:[玩转自定义TODO]( )
4. XML注释
在XML文档中,使用如下面格式注释:
<!--?注释内容?-->
其他:配置文件或mk文件等可使用#进行注释。
Android代码规范之Log开关
=================
在代码合适的地方添加Log输出,一般情况下我们的需求是希望debug状态下的输出log, 而release的包不希望输出log。一般我们在整个应用中应该使用和建立一个统一全局的Log开关类,方便统一开关管理。
可以定义自己的boolean变量来控制开关,这里介绍利用AS的BuildConfig.DEBUG属性来控制是否输出log,?gradle在编译debug包的时候BuildConfig类的DEBUG变量自动为true, 而编译release包的时候自动为false, 利用这点就可以实现在打debug包会自动输出log,?而release包的时候不会输出log。
使
用的时候无需关心当前debug状态:
即便代码里到处都是TQLog调用也没关系,因为release编译的时候Log会自动编译,只会在debug时才有输出。
另外,也可以在gradle中为BuildConfig添加自己的变量来控制log开关:
则代码中的log开关换成下面这句即可:
BuildConfig文件(自动生成在/build/generated/source/buildConfig/目录下)
PS:关于BuildConfig,AS里有一个坑,AS中依赖的module默认是 release状态的,所以BuildConfig的DEBUG总是false,
详情看这里:[解决依赖 library module的BuildConfig 坑]( )(重构项目中我已按照此方案解决) (AS3.0以后的版本此方案已失效)
Android Studio Gradle统一配置规范
===========================
其实这个不能说规范了,gradle是一个配置文件,不同的人和项目可能有不同的做法,这里只是列出来做一个参考,如果团队使用AS开发并且有很多项目,那么最好所有的项目gradle配置按照统一的规范来。
下面是我在项目中使用的一个app module下的gradle文件简单配置:
apply plugin: 'com.android.application'
//加载签名配置文件
Properties keyProps = new Properties()
keyProps.load(new FileInputStream(file("signing.properties")))
//加载服务器地址配置文件
Properties urlProps = new Properties()
urlProps.load(new FileInputStream(file("url.properties")))
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.aa.bb"
minSdkVersion rootProject.ext.libMinSdkVersion
targetSdkVersion 21
versionCode 5
versionName "3.1.1"
flavorDimensions "default"
manifestPlaceholders = [icon: "@drawable/app_logo", appname: "@string/app_name"]
}
signingConfigs {
dehug {
storeFile file(keyProps['DEBUG_KEYSTORE'])
storePassword keyProps['DEBUG_KEYSTORE_PWD']
keyAlias keyProps['DEBUG_ALIAS']
keyPassword keyProps['DEBUG_KEY_PWD']
}
release {
storeFile file(keyProps['KEYSTORE_FILE'])
storePassword keyProps['KEYSTORE_PWD']
keyAlias keyProps['KEY_ALIAS']
keyPassword keyProps['KEY_PWD']
}
}
buildTypes {
release {
buildConfigField "String", "HTTP_URL", urlProps['ReleaseUrl']
debuggable false
minifyEnabled true
zipAlignEnabled true
shrinkResources true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
buildConfigField "String", "HTTP_URL", urlProps['DebugUrl']
debuggable true
minifyEnabled false
zipAlignEnabled false
shrinkResources false
signingConfig signingConfigs.debug
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
packagingOptions {
//exclude "lib/armeabi/*.so"
//exclude "lib/armeabi-v7a/*.so"
//exclude "lib/arm64-v8a/*.so"
}
repositories {
flatDir {
//第一个libs是主项目的libs,其他module的libs路径需要用逗号隔开../module名/libs
dirs 'libs'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation(name:'base_lib-release', ext:'aar')
implementation(name:'imgselect_lib-release', ext:'aar')
implementation(name:'okgo_lib-release', ext:'aar')
implementation(name:'bottom_tabbar_lib-release', ext:'aar')
implementation(name:'recycler_adapter_lib-release', ext:'aar')
implementation(name:'quick_selector_lib-release', ext:'aar')
implementation(name:'audio_recorder_lib-release', ext:'aar')
implementation(name:'amap_location_lib-release', ext:'aar')
implementation(name:'amap_select_location_lib-release', ext:'aar')
implementation rootProject.ext.magicIndicator
implementation rootProject.ext.flexbox
implementation rootProject.ext.gson
implementation rootProject.ext.flycoDialog
implementation rootProject.ext.glide
implementation rootProject.ext.okhttp
implementation rootProject.ext.supportAppCompat
implementation rootProject.ext.supportV4
implementation rootProject.ext.recyclerView
}
其中像签名文件和服务器接口ip(分为正式和测试)分别放在signing.properties和url.properties文件中,而项目使用的第三方依赖库(除了aar是直接放在libs下面)如v4、v7包 gson依赖以及compile和target的sdk版本号配置等是统一配置在项目的根目录下的build.gradle文件中的:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
maven {
url "https://jitpack.io"
}
maven {
url 'https://maven.google.com'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// 这里统一配置项目的第三方版本依赖以及compile和target版本
ext {
libMinSdkVersion = 14
targetSdkVersion = 21
compileSdkVersion = 25
buildToolsVersion = '26.0.2'
supportAppCompat = 'com.android.support:appcompat-v7:25.3.1'
supportV4 = 'com.android.support:support-v4:25.3.1'
supportDesign = 'com.android.support:design:25.3.1'
recyclerView = 'com.android.support:recyclerview-v7:25.3.1'
flycoDialog = 'com.flyco.dialog:FlycoDialog_Lib:1.3.2@aar'
flexbox = 'com.google.android:flexbox:0.3.0'
glide = "com.github.bumptech.glide:glide:4.0.0"
gson = 'com.google.code.gson:gson:2.8.0'
最后我还整理了很多Android中高级的PDF技术文档。以及一些大厂面试真题解析文档。
Android高级架构师之路很漫长,一起共勉吧!