关于分支管理
git flow
图解
主分支
master
稳定分支,用于生产环境,与线上版本同步dev
开发分支,用于测试环境,用于构建测试版本,来源于master
流程分支
feature/xxx
功能分支,用于功能开发,来源于dev
,开发完成并自测通过后合并到dev
hotfix/xxx
修复分支,线上功能修复,来源于master
,修复后双向merge
到dev
和master
release/xxx
发布分支,版本发布使用,来源于dev
测试后的稳定代码,不应再发功能开发,发布后,要双向merge
到dev
和master
。
命名规范
所有命名都应该以业务为优先,并且避免通用命名的方法。另外命名不宜过长,但要表明功能。
- 关于关键字冲突
1 | thiz - this |
- 方法名使用小驼峰命名,首词应为动词
1 | public void doAnyThing() {} |
- 类名使用大驼峰命名
1 | class MainActivity {} |
- 数据类属性使用小驼峰命名
1 | class DataObj { |
- 业务类非静态属性使用
m + 大驼峰
命名
1 | class HomePresenter { |
- 业务类静态属性使用
s + 大驼峰
命名
1 | class HomePresenter { |
- 数据常量全部大些,下划线分隔
1 | public static final int TYPE_CUTOFF = 1; |
- 控件命名规范
1 | private TextView mNameTv; |
layout
资源命名
使用 bussiness_xxx.xml
的命名格式,做业务区分
1 | homepage_fragment_layout.xml |
id
命名
使用 R.id.function_view
的命名格式,这个规则与前面控件命名规范保持一致。
1 | R.id.content_tv |
- 禁止通用命名
禁止使用类似如下的通用字符串作为变量、方法、常量、资源、id 的名字
1 | list |
- 分包
本着业务优先的原则,分包方案应以业务模块为划分规则,而不应该以组件类型划分,如 activity
/fragment
/adapter
这种通用的包划分在项目业务膨胀后将会变得非常难管理。
按照业务划分,对以后的业务拆分和组件化也非常重要。
编码规范
- 属性注释
1 | public String name; // 姓名 |
- 方法注释
1 | /** |
- 常量提取,并提升到类的顶部
1 | public class MainViewModel { |
- 启动
Activity
和创建Fragment
使用静工厂封装/不用
1 | public class MainActivity extends MvvmActivity { |
xml
标签在行末闭合
1 | // good |
xml
中使用left/right
的地方,使用start/end
消除警告
1 | <ImageView |
- 拒绝硬编码
UI
主要体现在如果是一个列表结构,那么不应该在 xml
挨个罗列,应该在代码中使用循环的形式,动态 inflate
并 addView
,这样会具有更好的扩展性。
1 | LinearLayout container = helper.getView(R.id.container); |
- 使用
tools
命名空间,不要在xml
中编码非真实数据
1 | <TextView |
- 尽量使用
ConstraintLayout
,尽量不要使用weight
使用 ConstraintLayout
减少布局层级,使用 weight
会导致 measure
多次,应尽量不要使用 weight
。
- 代码格式化
提交代码之前应该先对代码进行格式化,包括 java
代码和 xml
代码。
使用相同的格式化规则能尽量减少代码的冲突。
- 每行代码不要过长
代码语句不应超过屏幕可观察范围太多,语句太长阅读起来麻烦,而且增加了理解的难度,应该使用中间变量做语句拆分。
- 内部类必须使用静态关键字声明
禁止使用非静态内部类,尤其是在 Activity
使用 Hander
/AsyncTask
等,静态内部类与宿主使用虚引用交互。
1 | public class MainActivity { |
- 生成
Bean
尽量不要使用 GsonFormat
,如果用了最后一定要检查生成的结果,不应该出现 类型为 Object
的属性。
使用范型组织 Bean
避免重复声明没有继承关系的 Bean
。
- 属性声明
不要在类文件中随意位置声明属性,所有属性声明应该提升到文件顶部,在静态常量声明之下。
属性应该尽量避免在声明时初始化,初始化代码放在初始化方法中。
- 避免使用魔法数字和字符串
1 | // good |
Handler
的使用
使用 Handler
必须使用静态内部类,并且在页面销毁时调用
1 | handler.removeCallbacksAndMessages(null); |
这对避免内存泄露至关重要
- 传递
Context
在任何传递 Context
都要非常慎重,尤其是单例等伪静态实现的情况。
如果不保证持有 Context
的对象可以被及时销毁,则应该使用 WeakRef
来持有上下文的引用。
- switch
switch
语法必须添加 default
分支。
所有的分支必须以 return
和 break
语句结束。
- if
if
分支遵循 fast stop
的原则,需要返回的地方优先结束流程。
只有一行的 if
语句,也需要使用 {}
1 | public void test(int num) { |
- 及时回收资源
这部分不再赘述,在编写一个页面的代码时,要在销毁页面的时候检查所有占用资源的对象手动回收资源。
- todo
测试代码使用 todo
标记,发版本时会检查禁止 todo
代码的出现。
- toast
toast
统一使用 HToast
封装后的,不要直接使用 ToastUtils
不方便切换。
海尔星球项目相关
- DTO
我们会对数据传输的类进行封装,这种类成为 DTO
,DTO
类根据使用场景不同继承 BaseXXXDTO
,不要声明多余的 DTO
类,后期不好维护,如果需要继承实现应该放在 dtos
文件夹下。
1 | Flowable<BaseDTO<VideoEntity>> testBaseDTO(); |
- 通信
通信建议依赖 EventBus
实现,所有事件继承 BaseEvent
,事件要合理分类,不要声明过多的 Event,所有的
Event` 类应该在各自业务逻辑包下面。
1 | public class LikeTagChooseEvent extends BaseEvent { |
- 数据类
数据类放在指定业务文件夹下面的 beans
包下面,并以 XXXBean
命名,统一路径和命名规则,可以简化混淆成本。
- 模块包结构
1 | - home |
- 路由管理
更好的页面管理方案应该是基于路由的,也就是 Activity
和 Activity
、Activity
和 Fragment
之间应该是松耦合,他们之间不应该有互相的引用
为了后面更好的向路由方案迁移,启动 Activity
和创建 Fragment
统一由 Router
管理
其他类调用 Router 类,启动 Activity
和创建 Fragment
,同时所有页面传输的 KEY
也在 Router
类里面注册,尽量复用。
- 网络请求
请求的
Service
集成在每个模块内部,比如首页的5
个请求,会在HomeApiService
里面,除非公共的请求,否则不要使用CommonService
,避免造成CommonService
臃肿和频繁的代码冲突。请求方法的命名,如果是
get
请求,方法命名为getXXX()
,post
请求,方法命名为postXXX()
,以此类推,方便看到请求就知道是什么请求方式。网络请求代码的编写
发起请求使用 Api.use(SomeService.class).xxx
,它是一个独立的网络请求管理者,你可以在任何位置使用它。
在 Model
层发起网络请求,并做数据处理,增强 Model
层的功能性,数据的处理使用 compose()
方法,在 ApiTransformers
中提供了大多数数据转换的方法,如果不能满足需求那么应该使用 map
函数再扩展,理论上不应在 Presenter
在做数据的转换和处理操作。
1 | public Observable<HomeTopStaticDTO> getIndexUnion() { |
在 Presenter
层接受转换后的数据,强制 使用 ApiObserver
的静态工厂创建观察者,不要自己创建,统一观察者方便做一些公共的事情,比如加载动画,统一错误处理等等,这至关重要。
创建观察者时,需要传入 View
层的标签,使请求可以绑定到生命周期,自动取消请求,建议使用 lambda
表达式的形式,它让我们更关注业务实现,而不是接口的名字。
1 | mModel.getIndexUnion().subscribe(ApiObserver.make(mView.viewTag(), data -> { |
综上,请大家遵循网络请求的模版代码,统一网络请求的格式。