8
8
9
9
* 这份代码规范文档开始编写的时间是 2020 年 7 月,中间不断地修改和补充,于 2021 年 1 月发布定稿,同年 2 月,纠正和补充了一些代码规范,从 0 到 1,从不成熟到成熟,整个过程耗时 200 多天。原因是我积累了很多开发的好习惯,但是一直没有任何记录,在短时间将这些东西全部输出几乎不可能,所以我前面花了很多时间回忆和总结,这段时间内我做的最多的一件事是,代码写着写着就去写代码规范文档,直到后面发布初稿时,我又投入了大把的时间和精力来做这件事。大家心中可能都有一个疑问,我为什么不用网上写的,直接照抄照搬,又或者直接采用阿里的,这样不是简单轻松多了?关于这个问题,可以跟大家谈谈我的想法,我看过很多关于 Android 代码规范文档,但是我感觉存在一些问题,可以跟大家分享一下:
10
10
11
- 1 . 没有说服力 :是很多代码规范文档只告诉你应该这样写,但是基本没有人提及这样写的好处,那样写不好的地方。他们只会告诉你规则,但是从不告诉你前因后果,这样写出来的代码规范难以服众。
11
+ 1 . 说服力低 :是很多代码规范文档只告诉你应该这样写,但是基本没有人提及这样写的好处,那样写不好的地方。他们只会告诉你规则,但是从不告诉你前因后果,这样写出来的代码规范难以服众。
12
12
13
13
2 . 不够全面:例如后台接口规范、接口实现规范、异常捕获规范、第三方框架使用规范、代码硬编码规范、资源硬编码规范、多模块规范;这些是我们开发中所避不开的东西,但是现在网上的代码规范文档却很少有人提及。
14
14
42
42
43
43
* [ 前言] ( #前言 )
44
44
45
+ * [ 代码规范原则] ( #代码规范原则 )
46
+
45
47
* [ 常规规范] ( #常规规范 )
46
48
47
49
* [ 后台接口规范] ( #后台接口规范 )
60
62
61
63
* [ 异常捕获规范] ( #异常捕获规范 )
62
64
63
- * [ Activity 跳转约定 ] ( #activity-跳转约定 )
65
+ * [ 参数传递规范 ] ( #参数传递规范 )
64
66
65
67
* [ 第三方框架使用规范] ( #第三方框架使用规范 )
66
68
104
106
105
107
* 经验总结:** 编码不规范,同行泪两行**
106
108
109
+ #### 代码规范原则
110
+
111
+ * 在讲之前,我们先想一个问题,代码规范的出现是为了什么?不就为了让我们更好地进行团队协作和项目维护吗?没错的,所以代码规范原则应该围绕这两点进行。
112
+
113
+ * ** 特事特办** :代码规范文档只能解决 ** 99.99%** 场景下的问题,特殊情况应该要特殊处理,违背者需要给出** 合理的解释** ,建议在代码中直接** 用注释注明** ,这样可以** 减少沟通成本** ,否则在一般情况下应当要遵守代码规范文档上的约束。
114
+
115
+ * ** 以人为本** :我们应该衡量不同写法带来的优点和缺点,然后根据当前项目的实际需求做出合适的选择或者变化。规则是人定的,不是** 一成不变** 的。在制定新的规则或者修改旧的规则之前应当先** 参考和分析** 谷歌或者知名公司的做法,然后与团队中的各个成员** 沟通和协商好** 。
116
+
117
+ * ** 实事求事** :任何代码规范都应该追求在实际开发中发挥的作用或者效果,规则始终是规则,不能单纯为了制定规则而编写代码规范,而是更应该追求写法的实用性,实用性应该从** 代码理解的难易程度** 、** 代码可维护性** 、** 代码可复用性** 、** 代码可扩展性** 等方面因素综合考虑,其次是考虑** 代码的视觉美观性** 。
118
+
107
119
#### 常规规范
108
120
109
121
* 使用 ** 0px** 代替 ** 0dp** ,这样就可以在获取时避免系统进行换算,提升代码的执行效率。
@@ -527,9 +539,9 @@ Glide.with(this)
527
539
528
540
* 所以尽量不要通过捕获的方式来处理异常,除非外层真的判断不了,否则应该通过一些逻辑判断来避免进入一些会 ** crash** 的代码。
529
541
530
- #### Activity 跳转约定
542
+ #### 参数传递规范
531
543
532
- * 应当将 Intent 中的 key 常量保存到一个管理类中,又或者定义在目标的 Activity 中
544
+ * 应当将 Intent 中的 key 常量保存到一个管理类中,如果不想单独定义一个 IntentKey 类,也可以直接将 key 值直接定义目标的 Activity 中。
533
545
534
546
``` java
535
547
public class IntentKey {
@@ -555,7 +567,7 @@ public class IntentKey {
555
567
}
556
568
```
557
569
558
- * 如果跳转的 Activity 需要传递参数,应该在目标的 Activity 中定义静态的 ** start** 又或者 ** newIntent** 方法
570
+ * 如果跳转的 Activity 需要传递参数,应该在目标的 Activity 中定义静态的 ** start** 又或者 ** newIntent** 方法。
559
571
560
572
``` java
561
573
public final class WebActivity extends Activity {
@@ -594,7 +606,124 @@ public final class WebFragment extends Fragment {
594
606
}
595
607
```
596
608
597
- * 如果跳转的 Activity 或者创建的 Fragment 不需要传任何参数,可以不需要定义这些静态方法
609
+ * 如果跳转的 Activity 或者创建的 Fragment 不需要传任何参数,可以不需要定义这些静态方法。
610
+
611
+ * 另外如果一个界面需要传递的参数过多(5 个以上),建议用一个对象对这些参数进行封装,然后实现 Serializable 或者 Parcelable 接口进行传递,具体写法示例:
612
+
613
+ ``` java
614
+ public final class VideoPlayActivity extends Activity {
615
+
616
+ /**
617
+ * 播放参数构建
618
+ */
619
+ public static final class Builder implements Parcelable {
620
+
621
+ /* * 视频源 */
622
+ private String mVideoSource;
623
+ /* * 视频标题 */
624
+ private String mVideoTitle;
625
+ /* * 播放进度 */
626
+ private int mPlayProgress;
627
+ /* * 手势开关 */
628
+ private boolean mGestureEnabled = true ;
629
+ /* * 循环播放 */
630
+ private boolean mLoopPlay = false ;
631
+ /* * 自动播放 */
632
+ private boolean mAutoPlay = true ;
633
+ /* * 播放完关闭 */
634
+ private boolean mAutoOver = true ;
635
+
636
+ public Builder () {}
637
+
638
+ public Builder setVideoSource (File file ) {
639
+ mVideoSource = file. getPath();
640
+ if (mVideoTitle == null ) {
641
+ mVideoTitle = file. getName();
642
+ }
643
+ return this ;
644
+ }
645
+
646
+ public Builder setVideoSource (String url ) {
647
+ mVideoSource = url;
648
+ return this ;
649
+ }
650
+
651
+ private String getVideoSource () {
652
+ return mVideoSource;
653
+ }
654
+
655
+ public Builder setVideoTitle (String title ) {
656
+ mVideoTitle = title;
657
+ return this ;
658
+ }
659
+
660
+ private String getVideoTitle () {
661
+ return mVideoTitle;
662
+ }
663
+
664
+ public Builder setPlayProgress (int progress ) {
665
+ mPlayProgress = progress;
666
+ return this ;
667
+ }
668
+
669
+ private int getPlayProgress () {
670
+ return mPlayProgress;
671
+ }
672
+
673
+ public Builder setGestureEnabled (boolean enabled ) {
674
+ mGestureEnabled = enabled;
675
+ return this ;
676
+ }
677
+
678
+ private boolean isGestureEnabled () {
679
+ return mGestureEnabled;
680
+ }
681
+
682
+ public Builder setLoopPlay (boolean enabled ) {
683
+ mLoopPlay = enabled;
684
+ return this ;
685
+ }
686
+
687
+ private boolean isLoopPlay () {
688
+ return mLoopPlay;
689
+ }
690
+
691
+ public Builder setAutoPlay (boolean enabled ) {
692
+ mAutoPlay = enabled;
693
+ return this ;
694
+ }
695
+
696
+ public boolean isAutoPlay () {
697
+ return mAutoPlay;
698
+ }
699
+
700
+ public Builder setAutoOver (boolean enabled ) {
701
+ mAutoOver = enabled;
702
+ return this ;
703
+ }
704
+
705
+ private boolean isAutoOver () {
706
+ return mAutoOver;
707
+ }
708
+
709
+ public void start (Context context ) {
710
+ Intent intent = new Intent (context, VideoPlayActivity . class);
711
+ intent. putExtra(IntentKey . VIDEO , this );
712
+ if (! (context instanceof Activity )) {
713
+ intent. addFlags(Intent . FLAG_ACTIVITY_NEW_TASK );
714
+ }
715
+ context. startActivity(intent);
716
+ }
717
+ }
718
+ }
719
+ ```
720
+
721
+ ``` java
722
+ new VideoPlayActivity .Builder ()
723
+ .setVideoTitle(" 速度与激情特别行动" )
724
+ .setVideoSource(" http://xxxxx.mp4" )
725
+ .start(getAttachActivity());
726
+ ```
598
727
599
728
#### 第三方框架使用规范
600
729
@@ -934,7 +1063,7 @@ button_round_selector.xml(通用圆角按钮样式)
934
1063
935
1064
#### Color ID 命名规范
936
1065
937
- * 请以 ** 模块 + 含义 + color** 来命名,例如:
1066
+ * 请以 ** 模块 + 作用 + color** 来命名,例如:
938
1067
939
1068
``` xml
940
1069
<color name =" logcat_level_verbose_color" >#FFBBBBBB</color >
@@ -993,10 +1122,10 @@ button_round_selector.xml(通用圆角按钮样式)
993
1122
<color name =" orange" >#FFFFA500</color >
994
1123
```
995
1124
996
- * 在实际开发中,我们常常会遇到下面这种命名方式 :
1125
+ * 在实际开发中,我们常常会遇到类似下面这种命名方式 :
997
1126
998
1127
``` xml
999
- <name =" color_FF35BF30" >#color_FF35BF30 </color >
1128
+ <name =" color_FF35BF30" >#FF35BF30 </color >
1000
1129
```
1001
1130
1002
1131
* 其实这种命名方式是不规范的,因为它对 ** Color ID** 的名称定义比较模糊,会容易给别人造成误导;举个例子:假设项目中有 ** 200** 个地方引用了这个 ` color_FF35BF30 ` 色值,其中有 ** 150** 地方是你自己引用的,另外 ** 50** 个地方是别人引用的,但是别人不知道你那个色值是干什么的,看到你有写就直接引用了,突然有一天产品经理心情不好要改这个色值,那么你要从 ** 200** 地方区分 ** 150** 个需要修改的地方和 ** 50** 个不需要修改的地方。
0 commit comments