美文网首页
Android 开发规范

Android 开发规范

作者: darren_he | 来源:发表于2016-07-07 18:26 被阅读409次

    前言

    在 Android 开发中,一个良好的开发习惯,以及一个开发规范可能会让你少走很多弯路,也会一定程度上的提高代码的可读性,可维护性和可拓展性。当随着需求的不断变更,代码量的不断增加,需要重构的时候,你会明白一个好的开发规范是多么的重要。

    1 命名规范

    1. 1 包名

    • 采用反域名命名规则,全部使用小写字母;
    • 一级包名为 com,二级包名为xxx(可以是公司域名或者个人命名),三级包名根据应用进行命名,四级包名为模块名或层级名。
    包名 说明
    com.xx.应用名称缩写.activity 页面用到的Activity类 (activitie层级名用户界面层)
    com.xx.应用名称缩写.base 基础共享的类
    com.xx.应用名称缩写.adapter 页面用到的Adapter类 (适配器的类)
    com.xx.应用名称缩写.util 此包中包含:公共工具方法类(util模块名)
    com.xx.应用名称缩写.bean 下面可分:vo、po、dto 此包中包含:JavaBean类
    com.xx.应用名称缩写.model 此包中包含:模型类
    com.xx.应用名称缩写.db 数据库操作类
    com.xx.应用名称缩写.view (或者 com.xx.应用名称缩写.widget ) 自定义的View类等
    com.xx.应用名称缩写.service Service服务
    com.xx.应用名称缩写.receiver BroadcastReceiver服务
    com.xx.应用名称缩写.pref 首选项
    • 只需导入用到的类,不得用*导入包下所有类;
    • 导入类时,系统类在上方,自定义类在下方。

    注意
    如果项目采用 MVP,所有 MVP 抽取出来的接口都放置在相应模块的 i 包 下,所有的实现都放置在相应模块的 impl 下


    1.2 类名

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

    描述 例如
    Activity 类 Activity 为后缀标识 欢迎页面类 WelcomeActivity
    Adapter 类 Adapter 为后缀标识 新闻详情适配器 NewDetailAdapter
    解析类 Parser 为后缀标识 首页解析类 HomePosterParser
    工具方法类 UtilManager 为后缀标识(与系统或第三方的 Utils 区分)或功能+Util 1. 线程池管理类:ThreadPoolManager;2. 日志工具类:LogUtil(Logger也可);3. 打印工具类:PrinterUtil
    数据库类 DBHelper 后缀标识 新闻数据库:NewDBHelper
    Service 类 Service 为后缀标识 时间服务 TimeService
    Receiver 类 Receiver 为后缀标识 推送接收 PushReceiver
    ContentProvider Provider 为后缀标识
    自定义的共享基础类 Base 开头 BaseActivity,BaseFragment
    • 测试类的命名以它要测试的类的名称开始,以 Test 结束。例如:HashTest 或 HashIntegrationTest
    • 接口(interface):命名规则与类一样采用大驼峰命名法,多以 ableible 结尾,如 interface Runable,interface Accessible

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


    1.3 方法名

    • 动词或动名词;
    • 采用小驼峰命名法。
    方法 说明
    initXX() 初始化相关方法,使用 init 为前缀标识,如初始化布局 initView()
    toXX() 按钮点击事件,如:toLogin()
    isXX() ,checkXX() 方法返回值为 boolean 型的请使用 is 或 check 为前缀标识
    setXX() 设置方法,使用 get 为前缀标识,如:setData()
    getXX() 返回某个值的方法,使用 get 为前缀标识
    handleXX() 对数据进行处理的方法,尽量使用 handle 为前缀标识
    displayXX(),showXX() 弹出提示框和提示信息,使用 display,show 为前缀标识
    saveXX() 与保存数据相关的,使用 save 为前缀标识
    resetXX() 对数据重组的,使用 reset 前缀标识
    clearXX() 清除数据相关的
    removeXXX() 清除数据相关的
    drawXXX() 绘制数据或效果相关的,使用 draw 前缀标识

    下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test_,例如testPop_emptyStack。并不存在唯一正确的方式来命名测试方法。


    1.4 常量名

    • 全部字母大写,用下划线分隔单词。
     public staticfinal String ACTION_MAIN="android.intent.action.MAIN";
    

    每个常量都是一个静态final字段,但不是所有静态final字段都是常量。在决定一个字段是否是一个常量时,考虑它是否真的感觉像是一个常量


    1.5 变量名

    • 非静态字段命名以 m 开头,表示 member,如:mRun;
    • 静态字段命名以 s 开头,表示 static,如:sInstance;
    • 公有非静态字段命名以 p 开头;
    • 公有静态字段(全局变量)命名以 g 开头;
    • 控件变量添加组件前缀,顺序在所有者前缀之后,例如:全局名称 mBtnNext,局部名称 btnNext。
    private int mPrivate;  
    protected int mProtected; 
    int mPackagePrivate; 
    private static MyClass sSingleton;  
    public int pField;  
    public static int gField; 
    
    • 除单例模式外一般不得使用静态变量;
    • 构造方法采用递增方式(参数多的写在后面);
    • 仅在项目内使用的实体类不使用JavaBean进行封装,直接将成员变量访问修饰符修改为非 private;
    • 实体类中固定值的成员变量可设置成 final,并通过构造函数初始化;
    • 实体类中不得随意修改的成员变量可添加下划线前缀以作区别,例如:
    class User{public int _id;}
    
    • 一般不使用 System.out 输出,而是使用 Log 中的方法;
    • 使用 BuildConfig.DEBUG 标记对 Log 进行封装,只在调试时输出重要信息,正式版不输出;
    • 一般 try……catch 只捕获需要的异常;
    • catch 块不得为空,至少应当将异常信息输出;

    说明
    集合添加如下后缀:List、Map、Set
    数组添加如下后缀:Arr


    2 资源文件命名

    2.1 Layout 命名

    • 全部小写,采用下划线命名法
    类型 说明 举例
    Activity 命名 activity_描述.xml activity_main.xml
    Fragment 命名 fragment_描述.xml fragment_hint.xml
    Dialog 命名 dialog_描述.xml dialog_hint.xml
    PopupWindow 命名 ppw_描述.xml ppw_info.xml
    ListView 的 item 命名 item_list_描述.xml item_list_city.xml
    GridView 的 item 命名 item_grid_描述.xml item_grid_city.xml
    ListView 的 HeaderView 命名 header_list_描述.xml header_list_city.xml
    ListView 的 FooterView 命名 item_list_描述.xml footer_list_city.xml
    包含项命名 模块_(位置)描述.xml activity_main_head.xml、activity_main_bottom.xml

    2.2 Drawable 命名

    • 全部小写,采用下划线命名法,加前缀区分
    类型 举例
    按钮 btn_main_home.png
    分割线 div_maket_white.png
    图标 ic_edit.png
    背景 bg_main.png
    默认 def_user_head_portrait.png

    如果有多种形态,如按钮等除

    名称 功能
    btn_xx 按钮图片使用 btn_整体效果
    btn_xx_normal 按钮图片使用 btn_正常情况效果
    btn_xx_pressed 按钮图片使用 btn_点击时候效果
    btn_xx_focused state_focused 聚焦效果
    btn_xx_disabled state_enabled (false) 不可用效果
    btn_xx_checked state_checked 选中效果
    btn_xx_selected state_selected 选中效果
    btn_xx_hovered state_hovered 悬停效果
    btn_xx_checkable state_checkable 可选效果
    btn_xx_activated state_activated 激活的
    btn_xx_windowfocused state_window_focused
    bg_head 背景图片使用 bg_功能_说明
    def_search_cell 默认图片使用 def_功能_说明
    ic_more_help 图标图片使用 ic_功能_说明
    seg_list_line 具有分隔特征的图片使用 seg_功能_说明
    sel_ok 选择图标使用sel_功能_说明

    2.3 Colors 的命名

    前缀{控件}{范围}{_后缀},控件、范围、后缀可选,但控件和范围至少要有一个

    • 背景颜色,添加 bg 前缀
    • 文本颜色,添加 text 前缀
    • 分割线颜色,添加 div 前缀
    • 区分状态时,默认状态的颜色,添加 normal 后缀
    • 区分状态时,按下时的颜色,添加 pressed 后缀
    • 区分状态时,选中时的颜色,添加 selected 后缀
    • 区分状态时,不可用时的颜色,添加 disable 后缀

    2.4 Strings 命名

    类型{范围}功能,范围可选。
    以下为几种常用的命名:

    • 页面标题,命名格式为:title_页面
    • 按钮文字,命名格式为:btn_按钮事件
    • 标签文字,命名格式为:label_标签文字
    • 选项卡文字,命名格式为:tab_选项卡文字
    • 消息框文字,命名格式为:toast_消息
    • 编辑框的提示文字,命名格式为:hint_提示信息
    • 图片的描述文字,命名格式为:desc_图片文字
    • 对话框的文字,命名格式为:dialog_文字
    • menu的item文字,命名格式为:action_文字

    2.5 动画命名

    • 全部小写,采用下划线命名法,加前缀区分

    普通的 tween 动画采用如下表格中的命名方式

    举例 说明
    fade_in 淡入
    fade_out 淡出
    push_down_in 从下方推入
    push_down_out 从下方退出
    push_left 推向左方
    slide_in_from_top 从头部滑动进入
    zoom_enter 变形进入
    slide_in 滑动进入
    shrink_to_middle 中间缩小

    2.6 Layout 中 id 的命名

    命名模式为:view缩写_view的逻辑名称

    <!-- 这是标题栏的标题 -->
    <TextView
        android:id="@+id/tv_header_title"
         ... />
    
    <!-- 这是登录按钮 -->
    <Button 
        android:id="@+id/btn_login"
        ... />
    

    ** 附录 **

    • 表1 UI 控件缩写表:
    控件 缩写 举例
    LinearLayout ll llFriend或者mFriendLL
    RelativeLayout rl rlMessage或mMessageRL
    FrameLayout fl flCart或mCartFL
    TableLayout tl tlTab或mTabTL
    Button btn btnHome或mHomeBtn
    ImageButton ibtn btnPlay或mPlayIBtn
    TextView tv tvName或mNameTV
    EditText et etName或mNameET
    ListView lv lvCart或mCartLV
    ImageView iv ivHead或mHeadIV
    GridView gv gvPhoto或mPhotoGV
    RadioButton rbtn -
    ToggleButton tbtn -
    CheckBox chk -
    View v -
    ScrollView sclv -
    ProgressBar pbar -
    • 表2 常见的英文单词缩写:
    名称 缩写
    icon ic(主要用在 app 的图标)
    color cl(主要用于颜色值)
    divider di(主要用于分隔线,不仅包括 Listview 中的 divider,还包括普通布局中的线)
    selector sl(主要用于某一 view 多种状态,不仅包括 Listview 中的 selector,还包括按钮的 selector)
    average avg
    background bg(主要用于布局和子布局的背景)
    buffer buf
    control ctrl
    delete del
    document doc
    error err
    escape esc
    increment inc
    infomation info
    initial init
    image img
    Internationalization I18N
    length len
    library lib
    message msg
    password pwd
    position pos
    server srv
    string str
    temp tmp
    window wnd(win)

    3 编码规范

    • 源文件编码格式为 UTF-8;
    • java代码中不出现中文,最多注释中可以出现中文;
    • 服务端可以实现的,就不要放在客户端;
    • 引用第三方库要慎重,避免应用大容量的第三方库,导致客户端包非常大;
    • 处理应用全局异常和错误,将错误以邮件的形式发送给服务端;
    • 图片的.9处理;
    • 使用静态变量方式实现界面间共享要慎重;
    • 单元测试(逻辑测试、界面测试);
    • 不要重用父类的 handler,对应一个类的 handler 也不应该让其子类用到,否则会导致 message.what 冲突;
    • strings.xml 中使用 %1$s 实现字符串的通配;
    • 数据一定要效验,例如字符型转数字型,如果转换失败一定要有缺省值;服务端响应数据是否有效判断;
    • 对于未完成的方法,使用 TODO 加以标记;
    void write(byte[] buf, File file) {
          // TODO: Write buf to file
    }
    
    • 若功能已完成,但存在效率等潜在问题时,使用 XXX 加以标记;
    void parseXML(File file) {
          // XXX: Maybe SAX is better
          DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = builder.parse(file);
    }
    
    • 若代码存在严重问题或仅用于调试,使用 FIXME 加以标记;
    boolean login(String name, String pwd) {
        // FIXME: Remove this line before publishing
        System.out.println("name=" + name + ", password=" + pwd);
        if (users.containsKey(name) && users.get(name).equals(pwd))
            return true;
            return false;
    }
    
    • 如果 for、while 等代码块过长,可以在结尾处标记循环变量
    for (int position = 0; position < 10; position++) {
        ……
    } // end for: position
        while (mRun) {
        ……
    } // end while: mRun
    
    • 如果 if 的条件大于2个,则必须写注释
    if (isBluetooth // If Bluetooth network is on
                     || isWifi // If WLAN network is on
                     || is3g // if 3g network is on
           ) {}
    

    4 代码提交规范

    无论使用的是 GIT,还是 SVN 都需要遵守下面这些规范;

    • 工作目录要及时更新,不要和服务器有太大的差别;
    • 提交代码时,如果出现冲突,必须仔细分析解决,不可以强行提交;
    • 提交代码之前先在本地进行测试,确保项目能编译通过,且能够正常运行,不可盲目提交;
    • 必须保证服务器上的版本是正确的,项目有错误时,不要进行提交;
    • 提交之前先更新;
    • 提交时注意不要提交本地自动生成的文件,比如我们 Android Studio 项目中的 ideabuild文件夹是不需要提交的;
    • 不要提交自己不明白的代码;
    • 提前协调好项目组成员的工作计划,减少冲突;
    • 对提交的信息采用明晰的标注(写注释)。

    5 架构规范

    5.1 架构方式

    是选择 MVP,MVC,MVVM ,Flux 还是 Clean 架构。 Dagger2 + RxJava + Retrofit/OkHtttp + Loader + Databinding + ContentProvider,还是谷歌官方架构示例android-architecture

    5.2 开源库的选取以及封装

    对开源库的选取,一般都需要选择比较稳定的版本,作者在维护的项目,要考虑作者对issue的解决,以及开发者的知名度等各方面。选取之后,一定的封装是必要的。

    5.3 架构提示

    抽象层面

    • 提高架构的拓展性是有必要的。以前的框架可能会出现功能不足的情况,但是因为这点是不可预见的,所以我们选择框架时一定要了解好框架本身的扩展性如何,或者对框架有较深的理解,能够自己扩展框架;
    • 提高架构的稳定性;
    • 必要的架构的文档;

    具体操作

    • Activity 和 Fragment 里面有许多重复的操作以及操作步骤,所以我们都需要提供一个 BaseActivity 和 BaseFragment ,让所有的 Activity 和 Fragment 都继承这个基类。
    • 数据提供统一的入口。无论是在 MVP、MVC 还是 MVVM 中,提供一个统一的数据入口,都可以让代码变得更加易于维护。
      比如,我使用的 DataManager,里面的 http、preference、eventpost、database ,都在 DataManger 里面进行操作,我们只需要与 DataManger 打交道。
    • 多用组合, 少用继承。
    • 提取方法, 去除重复代码。对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。
    • 引入 Dagger2 减少模块之间的耦合性。Dagger2 是一个依赖注入框架,使用代码自动生成创建依赖关系需要的代码。减少很多模板化的代码,更易于测试,降低耦合,创建可复用可互换的模块。
      Google官方MVP+Dagger2架构详解
    • 项目引入 RxJava + RxAndroid 这些响应式编程,可以极大的减少逻辑代码;
    • 通过引入事件总线,如:Event Bus、OTTO、RxBus。它允许我们在 Data Layer 中发送事件,以便 View Layer 中的多个组件都能够订阅到这些事件,减少回调。
    • 添加日志打印,用于查找错误等,如:loggertimber

    相关文章

      网友评论

          本文标题:Android 开发规范

          本文链接:https://www.haomeiwen.com/subject/sisljttx.html