Android 开发规范(基础版)

本文介绍了Android开发的一系列规范,包括代码格式、换行策略、命名约定、开发工具配置、Android代码结构、进程线程通信、文件数据库管理以及资源文件的命名和使用。遵循这些规范能提高代码可读性和维护性,有利于团队协作。建议使用最新稳定版Android Studio,配置代码格式,使用Alibaba Java编码规范插件。此外,还详细规定了函数链、多参数、RxJava链式调用的换行策略,以及避免在方法内部修改参数值等实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景 

项目的代码时间时间很长,经过太多人手,代码的规范性堪忧,目前存在较多的比较自由的「代码规范」,这非常不利于项目的维护,代码可读性也不够高。 分析现有项目的代码的情况,输出的『定制化规范』文档,用于提高代码的可读性和可维护性。

收益

对于个人:帮助团队写「正确」的代码,提升编程能力。

团队内部:统一项目的编码风格,降低维护『非自己模块』的成本

对外部门:交付更加稳定的产品,并降低后期的维护难度

开发工具配置规范

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

  • 推荐使用最新的稳定版本的 Android Studio 进行开发

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

  • 编辑完 .java、.kt、.xml 等文件后必须格式化(需要在设置好以下几点的前提下,Reformat Code 的必要性,一定需要保证 IDE 配置一致为前提,尽可能贴切于 Android Studio 默认。强烈建议对于比较长的老代码局部格式化,不全局格式化)

每行字符数不得超过100字符(IDE默认) 设置 Editor -> Code Style

Java代码格式规则(默认设置) 

  • 全部设置为单类导入

 XML代码格式规则(默认设置)

代码格式
  • 【强制】提交经过格式化的代码

  • 【强制】单行代码不要超过IDE右边界,单行字符数限制不超过100个(默认设置) 如果超出行长,我们通常有两种方法来缩减行长。 1.提取一个局部变量或方法(最好) 2.使用换行符将一行换成多行(参考『换行策略』)

  • 【强制】方法、参数、变量命名使用小骆驼拼写法(lowerCamelCase)

  • 【强制】方法之间需要空1行

  • 【强制】杜绝完全不规范的缩写,避免望文不知义。比如:condition“缩写”命名成 condi,英文拼音混合

  • 【强制】如果使用到了设计模式,建议在类名中体现出具体模式。

  • 【强制】方法调用的点符号与下文一起换行,在多个参数超长,在逗号后换行

换行策略(操作符"之前"换行,而逗号"之后"换行。)

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

操作符的换行

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

int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;

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

int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
        + theFinalOne;

函数链的换行

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

例如:

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

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

例如:

loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);
loadPicture(context,
        "https://blankj.com/images/avatar.jpg",
        ivAvatar,
        "Avatar of the user",
        clickListener);
RxJava 链式的换行

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

例如

public Observable<Location> syncLocations() {
    return mDatabaseHelper.getAllLocations()
            .concatMap(new Func1<Location, Observable<? extends Location>>() {
                @Override
                 public Observable<? extends Location> call(Location location) {
                     return mRetrofitService.getLocation(location.id);
                 }
            })
            .retry(new Func2<Integer, Throwable, Boolean>() {
                 @Override
                 public Boolean call(Integer numRetries, Throwable throwable) {
                     return throwable instanceof RetrofitError;
                 }
            });
}
  • 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用『单数形式』,但是类名如果有复数含义,类名可以使用『复数形式』。 正例: 应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考 spring 的框架结构)
  • 【参考】枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。

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

public class MainActivity extends Activity {
    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}

    @Override
    public void onResume() {}

    @Override
    public void onPause() {}

    @Override
    public void onDestroy() {}
}

方法的内部实现

  • 【强制】尽量使用lambda代替匿名内部类

  • 【极好】方法的参数和返回值,添加@NonNull,@Nullable注解 (包含其他androidx.anotation)

  • 【强制】无用的代码直接删除(检测:各自模块无用代码直接删除)

  • 【强制】不要任意添加try-catch,如果添加try-catch需要明确异常

  • 【强制】不要在方法内部修改参数的值(a方法调用,会影响后面的b方法)

  • 【推荐】单个方法实现不超过屏幕(80行,缩短代码行数,做好拆分)

  • 【推荐】方法内部不需要空行

  • 【推荐】不同业务View设置不同事件监听(例如OnClickListener)

  • 【推荐】if-else不要写反向逻辑

  • 【推荐】表达异常的分支时,少用 if-else 方式,这种方式可以改写成:if (condition) { return ; }

  • 【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。 正例: "test".equals(object); 反例: object.equals("test");

  • 【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式。

  • 【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

  • 【强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免使用 单行的形式:if (condition) statements;

  • 【推荐】除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

Android代码

Android基本组件

  • 【强制】Activity间通过隐式Intent的跳转,在发出Intent之前必须通过resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。

  • 【强制】Activity和Fragment的参数要使用@Autowired(原因:减少模板代码,支持ARouter跳转)

  • 【强制】避免在 BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作, 应该创建 IntentService 完成,而不应该在 BroadcastReceiver 内创建子线程去做。

  • 【强制】如果广播仅限于应用内,则可以使用LocalBroadcastManager.sendBroadcast()实现,避免敏感信息外泄和Intent拦截的风险。

  • 【推荐】优先考虑EventBus等框架代替Broadcast(如果操作轻量级,不涉及Intent和Context的情况下)

  • 【推荐】当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate 方法,所以在onPause方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率。

  • 【推荐】使用 Toast 时,建议定义一个全局的Toast对象,这样可以避免连续显示Toast 时不能取消上一次Toast消息的情况(如果你有连续弹出Toast的情况,避免使用Toast.makeText)。

  • 【强制】Activity或者Fragment中动态注册BroadCastReceiver时registerReceiver()和unregisterReceiver()要成对出现。否则可能导致已经注册的receiver没有在合适的时机注销,导致内存泄漏,占用内存空间,加重SystemService负担。

  • 【强制】同一方法禁止多次调用sp的apply(一些SPUtils只封装单次的提交,连续调用这样的方法就有这个问题)

  • 【强制】在Activity中显示对话框或弹出浮层时,尽量使用 DialogFragment,而非 Dialog/AlertDialog,这样便于随Activity生命周期管理对话框/弹出浮层的生命周期。

  • 【推荐】不能在 Activity 没有完全显示时显示 PopupWindow 和 Dialog

进程、线程与消息通信

  • 【强制】新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor 或者其他形式自定义的线程池),不允许在应用中自行显式创建线程。(需要线程池)

  • 【强制】线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor 的方 式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

  • 【推荐】ThreadPoolExecutor 设置线程存活时间(setKeepAliveTime),确保空闲时 线程能被释放。

文件与数据库

  • 【强制】任何时候不要硬编码文件路径,请使用 Android 文件系统 API 访问。

  • 【强制】当使用外部存储时,必须检查外部存储的可用性。

  • 【强制】应用间共享文件时,不要通过放宽文件系统权限的方式去实现,而应使用 FileProvider。

  • 【推荐】SharedPreference中只能存储简单数据类型(int、boolean、String等), 复杂数据类型建议使用文件、数据库等其他方式存储。

  • 【推荐】SharedPreference 提交数据时,尽量使用 Editor#apply(),而非 Editor#commit()。一般来讲,仅当需要确定提交结果,并据此有后续操作时,才使用Editor#commit()。

  • 【强制】数据库 Cursor 必须确保使用完后关闭,以免内存泄漏。

  • 【强制】多线程操作写入数据库时,需要使用事务,以免出现同步问题。

  • 【推荐】大数据写入数据库时,请使用事务或其他能够提高 I/O 效率的机制,保证执行速度。

  • 【强制】执行 SQL 语句时,应使用 SQLiteDatabase#insert()、update()、delete(), 不要使用 SQLiteDatabase#execSQL(),以免 SQL 注入风险。

Android资源文件

布局

  • 【推荐】推荐使用ConstraintLayout(必要时可以有内部嵌套),布局中不得使用ViewGroup多重嵌套(ConstraintLayout需要普及讲解)

  • 【强制】禁止在非ui线程进行 view 相关操作。

  • 【强制】禁止在设计布局时多次设置子 view和父view中为同样的背景造成页面过度绘制,推荐将不需要显示的布局进行及时隐藏。

  • 【推荐】灵活使用布局,推荐 Merge、ViewStub 来优化布局,尽可能多的减少 UI 布局层级。

  • 【极好】布局文件可以不用运行,仿真预览(使用tools)

Bitmap、Drawable 与动画

  • 【强制】加载大图片或者一次性加载多张图片,应该在异步线程中进行。图片的加载,涉及到I 操作,以及CPU密集操作,很可能引起卡顿。

  • 【强制】png 图片使用 tinypng 或者类似工具压缩处理,减少包体积。

  • 【强制】在 Activity.onPause()或 Activity.onStop()回调中,关闭当前 activity 正在执 行的的动画。

  • 【推荐】在动画或者其他异步任务结束时,应该考虑回调时刻的环境是否还支持业务处理。例如 Activity的onStop()函数已经执行,且在该函数中主动释放了资源,此时回调中如果不做判断就会空指针崩溃。

  • 【推荐】尽量减少Bitmap(BitmapDrawable)的使用,尽量使用纯色(ColorDrawable)、渐变色(GradientDrawable)、StateSelector(StateListDrawable)等与Shape结合的形式构建绘图。

Android 资源文件命名与使用

  • 【强制】资源文件需带模块前缀(公用放在base)

  • 【强制】动画资源文件(anim/和animator/)

Android主要包含属性动画和视图动画。属性动画文件需要放在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

中间缩小

  • 【强制】颜色资源文件(color/)

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

  • 【强制】图片资源文件(drawable/ 和 mipmap/)

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

命名规则:类型{_页面名称}{_逻辑名称}{_颜色}

说明:{}中的内容为可选;类型 可以是可绘制对象资源类型。 例如:

名称

说明

bg_input.png

输入框背景 类型_逻辑名称

bg_main.png

主页背景 类型_逻辑名称

bg_main_head.png

主页头部背景 类型_页面名称_逻辑名称

btn_back.png

返回按键 类型_逻辑名称

btn_main_about.png

主页关于按键 类型_页面名称_逻辑名称

btn_red.png

红色按键 类型_颜色

btn_red_big.png

红色大按键 类型_颜色

def_search_cell.png

搜索页面默认单元图片 类型_页面名称_逻辑名称

divider_list_line.png

列表分割线 类型_逻辑名称

divider_maket_white.png

商城白色分割线 类型_页面名称_颜色

divider_white.png

白色分割线 类型_颜色

ic_avatar_small.png

小头像图标 类型_逻辑名称

ic_edit.png

编辑图标 类型_逻辑名称

ic_more_help.png

更多帮助图标 类型_逻辑名称

sel_search_ok.xml

搜索界面确认选择器 类型_页面名称_逻辑名称

shape_music_ring.xml

音乐界面环形形状 类型_页面名称_逻辑名称

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

名称

说明

sel_btn_xx

作用在 btn_xx 上的 selector

btn_xx_normal

默认状态效果

btn_xx_pressedstate_pressed

点击效果

btn_xx_focusedstate_focused

聚焦效果

btn_xx_disabledstate_enabled

不可用效果

btn_xx_checkedstate_checked

选中效果

btn_xx_selectedstate_selected

选中效果

btn_xx_hoveredstate_hovered

悬停效果

btn_xx_checkablestate_checkable

可选效果

btn_xx_activatedstate_activated

激活效果

btn_xx_window_focusedstate_window_focused

窗口聚焦效果

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

  • 【强制】 布局资源文件(layout/)

命名规则:模块名_类型_

类型

名称

说明

Activity

passport_activity_main.xml

窗体页面 模块名_类型_页面名称

adapter 的列表项

my_item_main_song.xml

主页歌曲列表项 模块名_类型_页面名称_逻辑名称

Dialog

resume_dialog_loading.xml

加载对话框 模块名_类型_逻辑名称

Fragment

resume_fragment_music.xml

音乐片段 模块名_类型_逻辑名称

PopupWindow

position_popup_info.xml

信息弹窗(PopupWindow) 模块名_类型_逻辑名称

  • 【强制】视图layout布局的命名:view_float_live

  • 【强制】嵌套layout布局的命名:layout_title_bar(一般有复用)

  • 【强制】布局资源 id 命名

命名规则:类型小写_{模块名_}_逻辑名,例如:btn_main_search、btn_back。

  • 【推荐】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或者comment,应该放到一个按钮风格中,而不是在 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">#2a91db</color>
      <color name="orange">#ff9d2f</color>
      <color name="red">#ff432f</color>

  </resources>

向应用设计者那里要这个调色板,名称不需要跟 "green"、"blue" 等等相同。"brand_primary"、"brand_secondary"、"brand_negative" 这样的名字也是完全可以接受的。像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。通常一个具有审美价值的 UI 来说,减少使用颜色的种类是非常重要的。

  • 【强制】styles.xml

style的name命名使用大驼峰命名法,几乎每个项目都需要适当的使用 styles.xml 文件,因为对于一个视图来说,有一个重复的外观是很常见的,将所有的外观细节属性(colors、padding、font)放在 styles.xml 文件中。在应用中对于大多数文本内容,最起码你应该有一个通用的styles.xml 文件,例如:

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

应用到 TextView 中

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

【推荐】style 资源采用小写单词+下划线方式命名,写入 module_styles.xml 文件中, 采用以下规则:父style名称.当前style名称,如ParentTheme.ThisActivityTheme。

常见的视图控件缩写表

UI控件

缩写

LinearLayout

ll_

RelativeLayout

rl_

FrameLayout

fl_

Button

btn_

ImageButton

ibtn_

TextView

tv_

ImageView

iv_

RecyclerView

rv_

ConstraintLayout

cl_

ScollView | NestedScollView

sv_

CheckBox

cb_

RadioButton

rb_

RadioGroup

rg_

EditText

et_

View

v_

ViewPager | ViewPager2

vp_

自定义View

i_

ViewStub

vs_

include

in_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾阳Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值