1 命名规范
1.1 Android包命名规范
因为Android包目录的命名会直接影响到整个App工程后期的开发效率和扩展性,所以在创建项目的初期,包目录的命名非常重要。
Android工程本身对包目录命名没有要求,可以将代码文件直接放置在默认目录下,但这样做会导致很多无关文件的堆积,不利于查找及后期维护,所以一般不建议采用这种方式。Android包目录命名的常用方式有两种:PBL(Package By Layer)和PBF(Package By Feature)。
1. Package By Layer
PBL是按层次划分的,实际上就是按照职能划分,如在根目录里面命名activity、fragment、view、service、db、net、util、bean、base等包名。
例如,activity的职能是管理所有的Activity类,只要这个类是继承自Activity的,都放到这个目录下。以此类推,fragment目录存放所有继承自Fragment的类,view放置自定义的View,net放置网络相关的类,bean放置Bean对象等。
早期的Android App开发常采用图1.1所示的包结构。
接下来我们来分析一下PBL这种命名结构的优缺点。
1)PBL优点
- 项目结构简洁明了,上手快。
- 适合开发人员不多、项目功能简单、后期变动不大的项目。
2)PBL缺点
(1)低内聚
同一个目录下会有各种功能模块。例如activity目录,其中放置了登录、设置等功能模块;这几个模块本身并没有很强的关联性,却被放置在了一起,导致聚合性降低。(2)高耦合
这里讲的高耦合是指目录之间的关联性,例如activity目录内的类可能引用到了fragment或者view目录里面的类,导致目录之间的耦合性较高。
(3)影响开发效率
开发一个功能模块,往往需要在不同的包目录之间切换。例如登录模块,需要在activity目录下开发LoginActivity类,而LoginActivity类往往包含了fragment目录下的内容,这时又需要去fragment目录下找到对应的Fragment类来开发,目录之间频繁切换会影响开发效率。同样,修改、调试一个功能也需要进行这样的操作,如果后期项目功能和代码增多,会大大降低开发效率。
2. Package By Feature
PBF是按照功能划分包目录的。以功能模块名称作为目录名,所有与这个功能模块相关的开发都在这个目录内。以Google I/O 2019 Android App为例,如图1.2所示。
图1.2GoogleApp包目录结构.png
可以看到,除了与业务无关的模块,如utils这样的通用模块,每一个包目录都对应一个功能模块。
Google的项目采用PBF进行包目录命名,我们来分析一下PBF有哪些优点。
1)高内聚
所有功能都在一个包下完成,以map模块为例,如图1.3所示。可以看到,map目录下包含了fragment、adapter、viewmodel等。这里需要说明的是,功能模块里面的util一般都是和这个功能模块强相关的,如果是功能模块包目录外的util目录名,一般放置的是与项目相关的util类和能作用于整个或者多个功能模块的util类。其他包目录以此类推,例如ui包目录下面放置了Base Activity,adapter包目录下面放置了BaseAdapter等。
2)低耦合
包目录之间没有很强的关联性,此模块的功能只需要在对应的包目录下面即可进行开发,除了基础类外,一般不需要引入其他包的类。
3)开发效率高
增删改查都只需要在对应的包目录下面操作即可,便于团队开发管理,提升问题排查效率,也方便后续开发人员接手。
4)便于后期组件化转化
如果项目是按照PBF来进行包目录划分的,后期进行组件化改造的时候就会非常方便。可以直接把功能模块独立出来作为一个组件,同时划分好代码边界,对外保留好模块间的访问接口。例如上面的map功能模块,可以将其独立出来作为一个library工程。
1.2 Android代码命名规范
以Java语言为例,来说明一下如何制定代码的命名规范。命名规则约定事项如下。
- 代码命名不以下画线和美元符号开头。
- 【】表示可选。
1. 类名采用大驼峰命名法。
(1)命名规则【功能】 + 【类型】。
(2)举例Activity类,命名以Activity为后缀,如:LoginActivity。
Fragment类,命名以Fragment为后缀,如:ShareFragment。
Service类,命名以Service为后缀,如:DownloadService。
Dialog类,命名以Dialog为后缀,如:ShareDialog。
Adapter类,命名以Adapter为后缀,如:ProductAdapter。
BroadcastReceiver类,命名以Receiver为后缀,如:PushReceiver。
ContentProvider类,命名以Provider为后缀,如:FileProvider。
业务处理类,命名以Manager为后缀,如:UserManager。
解析类,命名以Parser为后缀,如:NewsParser。
工具类,命名以Util为后缀,如:EncryptUtil。
模型类,命名以Bean为后缀,如:GiftBean。
接口实现类,命名以Impl为后缀,如:DeviceImpl。
自定义共享基础类,命名以Base开头,如:BaseActivity。
测试类,命名以它要测试的类的名称开始,以Test结束,如:DeviceImplTest。
(3)抽象类和接口类
抽象类命名后缀为Abstract,如:abstract DeviceAbstract。
接口类命名后缀为Contract,如:interface DeviceContract。
2. 方法名采用小驼峰命名法。
(1)命名规则动词或动名词。如:run()、addDevice()。
(2)举例初始化方法,命名以init开头,如:initView。
按钮点击方法,命名以to开头,如:toLogin。
设置方法,命名以set开头,如:setData。
具有返回值的获取方法,命名以get开头,如:getData。
通过异步加载数据的方法,命名以load开头,如:loadData。
布尔型的判断方法,命名以is、has或check开头,如:isEmpty、checkNull。
对数据进行处理,命名以handle开头,如:handleUserInfo。
弹出提示框,命名以show开头,如:showAgreement。
更新数据,命名以update开头,如:updateUserInfo。
保存数据,命名以save开头,如:saveUserInfo。
重置数据,命名以reset开头,如:resetUserInfo。
删除数据,命名以delete开头,如:deleteUserInfo。
查询数据,命名以query开头,如:queryUserInfo。
移除数据,命名以remove开头,如:removeUserInfo。
3. 变量名
采用小驼峰命名法,变量命名应该简短且有规则。
所有变量都要显示地赋值,如int number =0。
布尔变量应该包含Is,如IsFirstLogin。
按照不同的变量类型,变量的命名规则有所不同,如下。
(1)类变量(成员变量)非公有的变量前面要加上小写m;
静态变量前面要加上小写s;
其他变量以小写字母开头,前面不再加任何前缀,例如Bean类中的属性变量,为了生成的get和set方法名美观可读,有一些IDE已经支持生成get和set方法名时自动去除前缀。
常量、静态变量全大写,采用下画线命名法。
public class Demo {
public static final int SOME_CONSTANT = 2022;
public int publicField = 1;
private static Demo sSingleton;
int mPackagePrivate;
private int mPrivate = 0;
protected int mProtected = 10;
}
(2)局部变量变量为一个单词,以小写字母开头。如:GiftBean bean。
(3)参数参数为一个或多个单词的组合,以小写字母开头。如:fun(int position)、fun(String userName)。
(4)临时变量临时变量通常被取名为i、j、k、m和n,它们一般用于整型;c、d、e一般用于字符型。如:for (int i = 0; i < len ; i++),for (String c : stringList)。
(5)泛型变量泛型变量一般用单个大写字母来表示,如果这个泛型是某个类的子类,那么这个大写字母一般取的是父类所代表的这个类含义的首字母。如:interface BasePresenter<V extends BaseView,M extends BaseModel> ,其中V代表View,M代表Model。
(6)控件变量Android中把很多UI控件作为成员变量,为了和Java的成员变量区分开,UI控件类型的成员变量在遵循前面成员变量命名规范的前提下,后面统一再加上控件名称。如:private TextView mDescriptionTextView。
有些命名规则是在后面加上控件的缩写,缩写不如全名看起来美观,而且不易于理解
1.3 Android资源文件命名规范
1. layout命名
全部小写,采用下画线命名法,使用名词或名词词组。所有Activity或Fragment等的布局名必须与其类名相对应。
(1)命名规则【类型名】+【模块名】。
(2)举例
MainActivity.java对应activity_main.xml,规则是类名单词倒置,中间用“”连接,并且单词全部改为小写,如下。
activity_main:Main模块的Activity。
fragment_login:Login模块的Fragment。
dialog_update:Update模块的Dialog。
关于include,由于include的布局一般不属于某个专门的模块,所以用include代表类型。
如果是在某个模块内拆分出来的布局,需要加上这个模块的名称,如下。
include_tips:提供tips布局。
include_im_function:IM模块的功能布局。
关于ListView、RecyclerView或GridView的item的布局命名,用item_代表类型,如下。
item_user_member:User模块下普通会员的item。
item_user_vip:User模块下VIP会员的item。
另外,item如果是表示header或footer的,可以加上_header或_footer后缀,如下。
item_user_header:User模块下下拉刷新的header。
item_user_footer:User模块下下拉刷新的footer。
总之,布局文件的命名需要能直接反映该布局文件的作用范围和功能。
2. layout中的id命名全部小写,采用下画线命名法。
(1)命名规则【控件缩写】+【模块名】+【功能名】。
(2)举例
<!-- 这是登录模块的密码输入框 -->
<TextView
android:id="@+id/et_login_password"
/>
<!-- 这是登录按钮 -->
<Button
android:id="@+id/btn_login_submit"
/>
有时候为了简洁,layout的id定义得不那么复杂,例如上面的et_login_password可能会写成password。这样有一个问题是,如果项目中存在多个相同的命名,那么查找起来会有些不方便,如图1.4所示的同名id
图1.4同名id.png
在单击main_content这个id名后,系统会弹出对话框提示选择跳转到哪一个layout下面的id。这样会增加开发时间,尤其是在对代码的熟悉程度不够的情况下。而且如果是在SDK中这样去命名,很有可能会导致引用SDK的项目出现资源重名并产生冲突。
-
anim
命名全部小写,采用下画线命名法。
(1)命名规则【模块名】+【动画类型】+【动画方向】。如果不限定模块名,表示这个动画是全局通用的。
(2)举例scale_in.xml:缩小;slide_out.xml:扩大。fade_in.xml:淡入;fade_out.xml:淡出。push_down_in.xml:从下方推入;push_down_out.xml:从下方推出。left_in.xml:从左边进入;left_out.xml:从左边退出。welcome_zoom_in.xml:欢迎界面放大。 -
mipmap(或drawable)
命名全部小写,采用下画线命名法。
(1)命名规则【控件缩写】+【模块名】+【功能名】+【状态限定】。状态限定的内容包括small、big、normal、focus、red、white等,且可以叠加。
(2)举例btn_main_back.png:Main模块的返回按钮的图片。
btn_main_back_small.png:Main模块的返回按钮的小图片。
btn_main_back_small_pressed.png:Main模块的返回按钮被选中时的小图片。
btn_red.png:通用红色按钮图片。
bg_setting.png:Setting模块通用背景图片。ic_user_head_small.png:User模块头像(小)。selector_login_input.png:Login模块输入文本框的selector。 -
values中的id命名
1)strings
(1)命名规则【模块名】+【控件名】+【功能名】。
(2)举例<string name="loading">加载中</string> <string name="button_ok">确定</string> <string name="dialog_title">对话框</string> <string name="main_titlebar_more">更多</string> <string name="setting_title">设置页面</string> <string name="search_edittext_hint">输入关键字</string> <string name="login_findpassword">找回密码</string>
2)colors
(1)命名规则【模块名或theme名】+【功能名】+【颜色编码】。
(2)举例
<!-- Basic colors -->
<color name="white">#FFFFFF</color>
<color name="black">#000000</color>
<color name="red">#FF0000</color>
<color name="blue">#0000FF</color>
<color name="green">#00FF00</color>
<!-- Splash page -->
<color name="splash_yellow">#EEEE00</color>
<color name="splash_pink">#FFB5C5</color>
<!-- Feedback page -->
<color name="feedback_submit_black">#000000</color>
3)dimens
(1)命名规则【模块名】+【控件名】+【描述】。
(2)举例
<!-- Common dimensions -->
<dimen name="margin_normal">16dp</dimen>
<dimen name="margin_small">8dp</dimen>
<dimen name="margin_large">32dp</dimen>
<!-- Navigation -->
<dimen name="nav_drawer_width">@dimen/match_parent</dimen>
<dimen name="nav_account_image_size">32dp</dimen>
<dimen name="nav_header_logo_size">36dp</dimen>
4)styles采用大驼峰命名法。
(1)命名规则【模块名.】+【功能名】。
(2)举例
<style name="ContentStyle">
<item name="android:layout_weight">1</item>
<item name="android:layout_width">0dp</item>
</style>
<style name="Login.ContentStyle">
<item name="android:layout_weight">1</item>
<item name="android:layout_width">0dp</item>
<item name="android:textSize">14sp</item>
<item name="android:gravity">center</item>
</style>
Android大部分编码就这些了,其他的规范可以依上面的思路进行设计。
网友评论