安卓app模板代码(5套独立的app手机端模板)

链接:

https://www.jianshu.com/p/e3afd461ebce

前言

虽然我们项目的代码时间并不长,也没经过太多人手,但代码的规范性依然堪忧,目前存在较多的比较自由的「代码规范」,这非常不利于项目的维护,代码可读性也不够高。

此外,客户端和后端的研发模式也完全不同,后端研发基本都是基于 SOA 思想的,通常一个子系统 3 个人一起维护就已经是很充分的人力了,更多时候就是 1 个主力 1 个 backup 的人力配置。

而客户端却完全不同,大家的代码都是相互交叉的,一个模块的代码可能要经历数十人的蹂躏,所以形成一个一致的开发规范迫在眉睫。

为什么需要一致的代码规范?

核心还是减少沟通成本,提升我们的 Code Review 效率,让我们的代码更加易于维护。此外,一个一致的代码规范可以造成更少的 bug,也就意味着更节省时间和金钱。

当然,规范是约定的,本系列文字全是笔者多年来博采众长,积累而成,所以有任何不同意见,欢迎评论拍砖。

1Android 的工具规范

工欲善其事,必先利其器。

由于 Android 基本都基于 Android Studio 进行开发,所以工具规范全部以 Android Studio 为前提。

必须使用最新的稳定版本的 Android Studio 进行开发;

编码格式必须统一为 UTF-8;

删除多余的import,减少警告出现,可利用 AS 的 Optimize Imports(Settings -> Keymap -> Optimize Imports)快捷键,设置自己的喜好。

安卓app模板代码(5套独立的app手机端模板)

Reformat Code 的必要性,一定需要保证 IDE 配置一致为前提,尽可能贴切于 Android Studio 默认。强烈建议对于比较长的老代码局部格式化,不全局格式化

每行字符数不得超过 160 字符,设置 Editor -> Code Style

全部设置为单路径引用,kotlinx.android.synthetic.main 除外。

Java Code Style

Kotlin Code Style

XML Code Style

以上几处设置完毕,其他采用 Android Studio 默认方式,再进行 Reformat Code 快捷键即可。

Reformat Code 快捷键设置

2Android 的分包规范

前面强调了工具的统一配置,再利用 Android Studio 本身的功能便可把代码风格变得一致。

接下来就带来第二部分:Android 的分包规范。

对于分包,我们需要达成一致,我们采用 PBF 方式,不推荐使用 PBL 方式。

PBF(按功能分包 Package By Feature)

PBL(按层分包 Package By Layer)

PBF 可能不是很好区分在哪个功能中,不过也比 PBL 要好找很多,且 PBF 与 PBL 相比较有如下优势:

package 内高内聚,package 间低耦合

哪块要添新功能,只改某一个 package 下的东西,而PBL 需要改多个 package,非常麻烦。

package 有私有作用域(package-private scope)

原则上一个 package 下的不允许其他类访问都是不应该加上 public 的。

很容易删除功能

统计发现新功能没人用,这个版本那块功能得去掉。如果是 PBL,得从功能入口到整个业务流程把受到牵连的所有能删的代码和 class 都揪出来删掉,一不小心就完蛋。如果是 PBF,好说,先删掉对应包,再删掉功能入口(删掉包后入口肯定报错了),完事。

高度抽象

解决问题的一般方法是从抽象到具体,PBF 包名是对功能模块的抽象,包内的 class 是实现细节,符合从抽象到具体,而 PBL 弄反了。PBF 从确定 AppName 开始,根据功能模块划分 package,再考虑每块的具体实现细节,而 PBL 从一开始就要考虑要不要 dao 层,要不要 com 层等等。

只通过 class 来分离逻辑代码

PBL 既分离 class 又分离 package,而 PBF 只通过 class 来分离逻辑代码。

package 的大小有意义了

PBL 中包的大小无限增长是合理的,因为功能越添越多,而 PBF 中包太大(包里 class 太多)表示这块需要重构(划分子包)。

3Android 的命名规范

代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。正确的英文拼写和语法可以让阅读者易于理解,避免歧义。

注意:即使纯拼音命名方式也要避免采用。但国际通用的名称,可视同英文,比如 toutiao、douyin 等。

3.1 包名

Android 里面有 package 的概念,所以需要约定一下包名命名规范。

包名全部小写,不允许出现中文、大写字母或者下划线,前面为子模块命名,再根据 PBF 方式进行命名。

3.2 类名

类名都以 UpperCamelCase 风格编写。

类名通常是名词或名词短语,接口名称有时可能是形容词或形容词短语。现在还没有特定的规则或行之有效的约定来命名注解类型。

名词,采用大驼峰命名法,尽量避免缩写,除非该缩写是众所周知的, 比如 HTML、URL,如果类名称中包含单词缩写,则单词缩写的每个字母均应大写。

类描述例如Activity类模块名 Activity闪屏页类SplashActivityFragment类模块名 Fragment主页类HomeFragmentService类模块名 Service时间服务TimeServiceBroadcastReceiver类功能名 Receiver推送接收JPushReceiverContentProvider类功能名 ProviderShareProvider自定义 View功能名 View/ViewGroup(组件名称)ShapeButtonDialog对话框功能名 DialogImagePickerDialogAdapter类模块名 Adapter课程详情适配器LessonDetailAdapter解析类功能名 Parser首页解析类HomePosterParser工具方法类功能名 Utils或Manager线程池管理类:ThreadPoolManager日志工具类:LogUtils(Logger也可)打印工具类:PrinterUtils数据库类功能名 DBHelper新闻数据库:NewsDBHelper自定义的共享基础类Base 基础BaseActivity,BaseFragment抽象类Base/Abstract开头AbstractLogin异常类Exception结尾LoginException接口able/ible结尾 / I 开头Runnable,Accessible,ILoginView

测试类的命名以它要测试的类的名称开始,以 Test 结束。例如:HashTest 或 HashIntegrationTest。

接口(interface):命名规则与类一样采用大驼峰命名法,多以 able 或 ible 结尾,如 interface Runnable、interface Accessible。

注意:如果项目采用 MVP,所有 Model、View、Presenter 的接口都以 I 为前缀,不加后缀,其他的接口采用上述命名规则。

3.3 方法名

方法名都以 lowerCamelCase 风格编写。

方法名通常是动词或动词短语。

方法说明initXX()初始化相关方法,使用 init 为前缀标识,如初始化布局initView()isXX(),checkXX()方法返回值为 boolean 型的请使用 is/check 为前缀标识getXX()返回某个值的方法,使用 get 为前缀标识setXX()设置某个属性值handleXX(),processXX()对数据进行处理的方法displayXX(),showXX()弹出提示框和提示信息,使用 display/show 为前缀标识updateXX()更新数据saveXX(),insertXX()保存或插入数据resetXX()重置数据clearXX()清除数据removeXX(),deleteXX()移除数据或者视图等,如removeView()drawXX()绘制数据或效果相关的,使用 draw 前缀标识3.4 变量命名

这里的变量为广义的变量,包括了常量、局部变量、全局变量等,它们的基础规则是:

类型需要是名词 / 名词短语;

采用 lowerCamelCase 风格;

在具体的变量命名时,会根据该变量的类型不同而附加额外的命名规则:

类型说明例如常量大写 & 下划线隔开,Kotlin 一定要 const valconst val TYPE_NORMAL = 1static final TYPE_NORMAL = 1临时变量名整型:i、j、k、m、n ,字符型一般用 c、d、efor(int i = 0;i < len; i )其他变量lowerCamelCase风格即可,私有变量也不要使用m开头private int tmp;Kotlin只读变量使用val,可变变量使用var,尽可能使用valvar tmp = 0val defaultIndex = 03.5 资源命名

Android 的资源包括:

资源文件命名为全部小写,采用下划线命名法。

3.5.1 动画资源文件(anim/ 和 animator/)

安卓主要包含属性动画和视图动画,其视图动画包括补间动画和逐帧动画。属性动画文件需要放在 res/animator/目录下,视图动画文件需放在 res/anim/目录下。命名规则:{模块名_}逻辑名称。

说明:{}中的内容为可选,逻辑名称可由多个单词加下划线组成。例如:refresh_progress.xml、market_cart_add.xml、market_cart_remove.xml。

如果是普通的补间动画或者属性动画,可采用:动画类型_方向的命名方式。

例如:

名称说明fade_in淡入fade_out淡出push_down_in从下方推入push_down_out从下方推出push_left推向左方slide_in_from_top从头部滑动进入zoom_enter变形进入slide_in滑动进入shrink_to_middle中间缩小3.5.2 颜色资源文件(color/)

color/ 是专门用于存放颜色相关资源的文件夹。命名规则:类型{_模块名}_逻辑名称。

说明:{}中的内容为可选。例如:sel_btn_font.xml。

颜色资源也可以放于 res/drawable/目录,引用时则用@drawable 来引用,但不推荐这么做,最好还是把两者分开。

3.5.3 图片资源文件(drawable/ 和 mipmap/)

res/drawable/目录下放的是位图文件(.png、.9.png、.jpg、.gif)或编译为可绘制对象资源子类型的 XML 文件,而 res/mipmap/目录下放的是不同密度的启动图标,所以 res/mipmap/只用于存放启动图标,其余图片资源文件都应该放到 res/drawable/目录下。

命名规则:类型{_模块名}_逻辑名称、类型{_模块名}_颜色。

说明:{}中的内容为可选;类型可以是可绘制对象资源类型,也可以是控件类型最后可加后缀_small 表示小图,_big 表示大图。

例如:

如果有多种形态,如按钮选择器:sel_btn_xx.xml,采用如下命名:

注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector,前提是命名要规范。

3.5.4 布局资源文件(layout/)

命名规则:类型_模块名、{模块名_}类型_逻辑名称。(也采用 PBF,方便查看,尤其在大项目中)

说明:{}中的内容为可选。

例如:

类型名称说明Activitymain_activity.xml主窗体模块名_类型Fragmentmusic_fragment.xml音乐片段模块名_类型Dialogloading_dialog.xml加载对话框逻辑名称_类型PopupWindowinfo_ppw.xml信息弹窗(PopupWindow)逻辑名称_类型adapter的列表项main_song_item.xml主页歌曲列表项模块名_类型_逻辑名称3.5.5 布局资源 id 命名

命名规则:{模块名_}_逻辑名_view 缩写(功能),例如:main_search_btn、back_btn。此外,采用 Kotlinx 直接获取布局文件的时候,id 命名采用驼峰样式。

说明:{}中的内容为可选。参考 GoogleSamples Demo:https://github.com/android/architecture-samples

例如:

类型规范命名示例TextViewxxx_textuser_login_textEditTextxxx_edituser_login_editImageViewxxx_ivuser_login_ivButtonxxx_btnuser_login_btnCheckBoxxxx_cbuser_login_cbGridViewxxx_gvuser_login_gvListViewxxx_lvuser_login_lvRecyclerViewxxx_rvuser_login_rvRadioButtonxxx_rbuser_login_rbLinearLayoutxxx_lluser_login_llRelativeLayoutxxx_rluser_login_rlFrameLayoutxxx_fluser_login_flGridLayoutxxx_gluser_login_glConstraintLayoutxxx_cluser_login_cl3.5.6 菜单资源文件(menu/)

菜单相关的资源文件应放在该目录下。命名规则:{模块名_}逻辑名称

说明:{}中的内容为可选。例如:main_drawer.xml、navigation.xml。

3.5.7 colors.xml

<color>的 name 命名使用下划线命名法,在你的 colors.xml 文件中应该只是映射颜色的名称一个 ARGB 值,而没有其它的。不要使用它为不同的按钮来定义 ARGB 值。

例如,不要像下面这样做:

<resources><colorname=”button_foreground”>#FFFFFF</color><colorname=”button_background”>#2A91BD</color><colorname=”comment_background_inactive”>#5F5F5F</color><colorname=”comment_background_active”>#939393</color><colorname=”comment_foreground”>#FFFFFF</color><colorname=”comment_foreground_important”>#FF9D2F</color>…<colorname=”comment_shadow”>#323232</color>

使用这种格式,会非常容易重复定义 ARGB 值,而且如果应用要改变基色的话会非常困难。同时,这些定义是跟一些环境关联起来的,如 button 或者 comment,应该放到一个按钮风格中,而不是在 colors.xml 文件中。

相反,应该这样做:

<resources><!–grayscale–><colorname=”white”>#FFFFFF</color><colorname=”gray_light”>#DBDBDB</color><colorname=”gray”>#939393</color><colorname=”gray_dark”>#5F5F5F</color><colorname=”black”>#323232</color><!–basiccolors–><colorname=”green”>#27D34D</color><colorname=”blue”>#2A91BD</color><colorname=”orange”>#FF9D2F</color><colorname=”red”>#FF432F</color></resources>

向应用设计者那里要这个调色板,名称不需要跟”green”、”blue”等等相同。”brand_primary”、”brand_secondary”、”brand_negative”这样的名字也是完全可以接受的。

像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。通常一个具有审美价值的 UI 来说,减少使用颜色的种类是非常重要的。

注意:如果某些颜色和主题有关,那就单独写一个 colors_theme.xml。

3.5.8 strings.xml

<string>的 name 命名使用下划线命名法,采用以下规则:{模块名_}逻辑名称,这样方便同一个界面的所有 string 都放到一起,方便查找。

名称说明main_menu_about主菜单按键文字friend_title好友模块标题栏friend_dialog_del好友删除提示login_check_email登录验证dialog_title弹出框标题button_ok确认键loading加载文字3.5.9 styles.xml

<style>的 name 命名使用大驼峰命名法,几乎每个项目都需要适当的使用 styles.xml 文件,因为对于一个视图来说,有一个重复的外观是很常见的,将所有的外观细节属性(colors、padding、font)放在 styles.xml 文件中。

在应用中对于大多数文本内容,最起码你应该有一个通用的 styles.xml 文件,例如:

<stylename=”ContentText”><itemname=”android:textSize”>@dimen/font_normal</item><itemname=”android:textColor”>@color/basic_black</item></style>

应用到 TextView 中:

<TextViewandroid:layout_width=”wrap_content”android:layout_height=”wrap_content”android:text=”@string/price”style=”@style/ContentText”/>

或许你需要为按钮控件做同样的事情,不要停止在那里,将一组相关的和重复 android:xxxx的属性放到一个通用的<style>中。

4Android 的注释规范

4.1 类注释

/***<pre>*author:nanchen*e-mail:xxx@xx*time:2021/01/18*desc:xxxx描述*version:1.0*</pre>*/publicclassWelcomeActivity{…}

具体可以在 AS 中自己配制,进入 Settings -> Editor -> File and Code Templates -> Includes -> File Header,输入:

/***<pre>*author:${USER}*e-mail:xxx@xx*time:${YEAR}/${MONTH}/${DAY}*desc:*version:1.0*</pre>*/

这样便可在每次新建类的时候自动加上该头注释。

4.2 方法注释

每一个成员方法(包括自定义成员方法、覆盖方法、属性方法)的方法头都必须做方法头注释,在方法前一行输入/** 回车或者设置 Fix doc comment(Settings -> Keymap -> Fix doc comment)快捷键,AS 便会帮你生成模板,我们只需要补全参数即可,如下所示。

@param , @return , @throws , @deprecated 这 4 种标记出现的时候,描述都不能为空。当描述无法在一行中容纳,连续行至少需要再缩进 4 个空格。

/***Reportanaccessibilityactiontothisview’sparentsfordelegatedprocessing.**<p>Implementationsof{@link#performAccessibilityAction(int,Bundle)}mayinternally*callthismethodtodelegateanaccessibilityactiontoasupportingparent.Iftheparent*returnstruefromits*{@linkViewParent#onNestedPrePerformAccessibilityAction(View,int,android.os.Bundle)}*methodthismethodwillreturntruetosignifythattheactionwasconsumed.</p>**<p>Thismethodisusefulforimplementingnestedscrollingchildviews.If*{@link#isNestedScrollingEnabled()}returnstrueandtheactionisascrollingaction*acustomviewimplementationmayinvokethismethodtoallowaparenttoconsumethe*scrollfirst.Ifthismethodreturnstruethecustomviewshouldskipitsownscrolling*behavior.</p>**@paramactionAccessibilityactiontodelegate*@paramargumentsOptionalactionarguments*@returntrueiftheactionwasconsumedbyaparent*/publicbooleandispatchNestedPrePerformAccessibilityAction(intaction,Bundlearguments){for(ViewParentp=getParent();p!=null;p=p.getParent()){if(p.onNestedPrePerformAccessibilityAction(this,action,arguments)){returntrue;}}returnfalse;}4.3 块注释

块注释与其周围的代码在同一缩进级别。它们可以是/* … */风格,也可以是// … 风格(//后最好带一个空格)。对于多行的/* … */注释,后续行必须从*开始, 并且与前一行的*对齐。以下示例注释都是 OK 的。

/**Thisisokay.*///Andso//isthis./*Oryoucan*evendothis.*/

注释不要封闭在由星号或其它字符绘制的框架里。

Tip:在写多行注释时,如果你希望在必要时能重新换行(即注释像段落风格一样),那么使用/* … */。

比如:

4.4 全局变量的注释

全局变量的注释样式如下(注意注释之间有空格):

/***Thenextavailableaccessibilityid.*/privatestaticintnextAccessibilityViewId;/***Theanimationcurrentlyassociatedwiththisview.*/protectedAnimationcurrentAnimation=null;4.5 其他一些注释

AS 已帮你集成了一些注释模板,我们只需要直接使用即可,在代码中输入 TODO、FIXME 等这些注释模板,回车后便会出现如下注释。

//TODO:17/3/14需要实现,但目前还未实现的功能的说明//FIXME:17/3/14需要修正,甚至代码是错误的,不能工作,需要修复的说明4.5 注释必须遵守的规范

4.5.1 不言自明的方法不要加注释。

比如 Item getItem(int index)是一段自说明的代码,我们可以直接从方法的命名就能知道它是干嘛的,所以不需要增加注释。

4.5.2 提测的代码不应该有 TODO 这样的注释

5代码样式规范

5.1 使用标准大括号样式

左大括号不单独占一行,与其前面的代码位于同一行:

classMyClass{intfunc(){if(something){//…}elseif(somethingElse){//…}else{//…}}}

我们需要在条件语句周围添加大括号。例外情况:如果整个条件语句(条件和主体)适合放在同一行,那么您可以(但不是必须)将其全部放在一行上。例如,我们接受以下样式:

if(condition){body();}

同样也接受以下样式:

if(condition)body();

但不接受以下样式:

if(condition)body();//bad!5.2 编写简短方法

在可行的情况下,尽量编写短小精炼的方法。我们了解,有些情况下较长的方法是恰当的,因此对方法的代码长度没有做出硬性限制。如果某个方法的代码超出 40 行,请考虑是否可以在不破坏程序结构的前提下对其拆解。

5.3 类成员的顺序

这并没有唯一的正确解决方案,但如果都使用一致的顺序将会提高代码的可读性,推荐使用如下排序:

常量(Kotlin 伴生对象放在开头)

字段

构造函数

重写函数和回调

公有函数

私有函数

内部类或接口

例如:

publicclassMainActivityextendsActivity{privatestaticfinalStringTAG=MainActivity.class.getSimpleName();privateStringmTitle;privateTextViewmTextViewTitle;@OverridepublicvoidonCreate(){…}publicvoidsetTitle(Stringtitle){mTitle=title;}privatevoidsetUpView(){…}staticclassAnInnerClass{}}

如果类继承于 Android 组件(例如 Activity 或 Fragment),那么把重写函数按照他们的生命周期进行排序是一个非常好的习惯,例如,Activity 实现了 onCreate()、onDestroy()、onPause()、onResume(),它的正确排序如下所示:

publicclassMainActivityextendsActivity{//OrdermatchesActivitylifecycle@OverridepublicvoidonCreate(){}@OverridepublicvoidonResume(){}@OverridepublicvoidonPause(){}@OverridepublicvoidonDestroy(){}}5.4 函数参数的排序

在 Android 开发过程中,Context 在函数参数中是再常见不过的了,我们最好把 Context 作为其第一个参数。

正相反,我们把回调接口应该作为其最后一个参数。

例如:

//ContextalwaysgoesfirstpublicUserloadUser(Contextcontext,intuserId);//CallbacksalwaysgolastpublicvoidloadUserAsync(Contextcontext,intuserId,UserCallbackcallback);

5.5 字符串常量的命名和值

Android SDK 中的很多类都用到了键值对函数,比如 SharedPreferences、Bundle、Intent,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。

当时用到这些类的时候,我们必须将它们的键定义为 static final 字段,并遵循以下指示作为前缀。

类字段名前缀SharedPreferencesPREF_BundleBUNDLE_Fragment ArgumentsARGUMENT_Intent ExtraEXTRA_Intent ActionACTION_

说明:虽然 Fragment.getArguments()得到的也是Bundle ,但因为这是 Bundle 的常用用法,所以特意为此定义一个不同的前缀。

例如:

//注意:字段的值与名称相同以避免重复问题staticfinalStringPREF_EMAIL=”PREF_EMAIL”;staticfinalStringBUNDLE_AGE=”BUNDLE_AGE”;staticfinalStringARGUMENT_USER_ID=”ARGUMENT_USER_ID”;//与意图相关的项使用完整的包名作为值的前缀staticfinalStringEXTRA_SURNAME=”com.myapp.extras.EXTRA_SURNAME”;staticfinalStringACTION_OPEN_USER=”com.myapp.action.ACTION_OPEN_USER”;5.6 行长限制

代码中每一行文本的长度都应该不超过 160 个字符。虽然关于此规则存在很多争论,但最终决定仍是以 160 个字符为上限,如果行长超过了 160(AS 窗口右侧的竖线就是设置的行宽末尾 ),我们通常有两种方法来缩减行长。

提取一个局部变量或方法(最好)。

使用换行符将一行换成多行。

不过存在以下例外情况:

如果备注行包含长度超过 160 个字符的示例命令或文字网址,那么为了便于剪切和粘贴,该行可以超过 160 个字符。

导入语句行可以超出此限制,因为用户很少会看到它们(这也简化了工具编写流程)。

5.6.1 换行策略

这没有一个准确的解决方案来决定如何换行,通常不同的解决方案都是有效的,但是有一些规则可以应用于常见的情况。

5.6.1.1 操作符的换行

除赋值操作符之外,我们把换行符放在操作符之前,例如:

intlongName=anotherVeryLongVariable anEvenLongerOne-thisRidiculousLongOne theFinalOne;

赋值操作符的换行我们放在其后,例如:

intlongName=anotherVeryLongVariable anEvenLongerOne-thisRidiculousLongOne theFinalOne;5.6.1.2 函数链的换行

当同一行中调用多个函数时(比如使用构建器时),对每个函数的调用应该在新的一行中,我们把换行符插入在 . 之前。

例如:

Picasso.with(context).load(“https://blankj.com/images/avatar.jpg”).into(ivAvatar);

我们应该使用如下规则:

Picasso.with(context).load(“https://blankj.com/images/avatar.jpg”).into(ivAvatar);5.6.1.3 多参数的换行

当一个方法有很多参数或者参数很长的时候,我们应该在每个 , 后面进行换行。

比如:

loadPicture(context,”https://blankj.com/images/avatar.jpg”,ivAvatar,”Avataroftheuser”,clickListener);

我们应该使用如下规则:

loadPicture(context,”https://blankj.com/images/avatar.jpg”,ivAvatar,”Avataroftheuser”,clickListener);5.6.1.4 RxJava 链式的换行

RxJava 的每个操作符都需要换新行,并且把换行符插入在 . 之前。

例如:

publicObservable<Location>syncLocations(){returnmDatabaseHelper.getAllLocations().concatMap(newFunc1<Location,Observable<?extendsLocation>>(){@OverridepublicObservable<?extendsLocation>call(Locationlocation){returnmRetrofitService.getLocation(location.id);}}).retry(newFunc2<Integer,Throwable,Boolean>(){@OverridepublicBooleancall(IntegernumRetries,Throwablethrowable){returnthrowableinstanceofRetrofitError;}});}

参考文档:

https://source.android.com/source/code-style?hl=zh-cn

https://developer.android.com/kotlin/style-guide?hl=zh-cn

https://github.com/Blankj/AndroidStandardDevelop

推荐阅读:

App极限瘦身姿势: png 打包自动化转换 webp“终于懂了” 系列:Android组件化,全面掌握!这交互炸了系列,炫酷跳动的闪屏Logo标题

发表评论

登录后才能评论