|
38 | 38 |
|
39 | 39 | #### 3.1 包名
|
40 | 40 |
|
41 |
| -包名全部小写,连续的单词只是简单地连接起来,不使用下划线。 |
| 41 | +包名全部小写,连续的单词只是简单地连接起来,不使用下划线,采用反域名命名规则,全部使用小写字母。一级包名是顶级域名,通常为`com`,`edu`,`gov`,`net`,`org`等,二级包名为公司名,三级包名根据应用进行命名,后面就是对包名的划分了,关于包名的划分,推荐使用按功能分,一开始我们也是按照层去分包的,很坑爹。按照功能分可能你不是很好区分在哪个功能中,不过也比你按照层区分要好找很多。具体可以参考这篇博文~**[Package by features, not layers][Package by features, not layers]**,当然,我们大谷歌也有相应的sample~**[iosched][iosched]**,其结构如下所示,很值得学习。 |
42 | 42 |
|
43 |
| -采用反域名命名规则,全部使用小写字母。一级包名是顶级域名,通常为`com`,`edu`,`gov`,`net`,`org`等,二级包名为公司名,三级包名根据应用进行命名,四级包名为模块名或层级名。 |
| 43 | +``` |
| 44 | +java |
| 45 | +└─com |
| 46 | + └─google |
| 47 | + └─samples |
| 48 | + └─apps |
| 49 | + └─iosched |
| 50 | + │ AppApplication.java 定义Application类 |
| 51 | + │ Config.java 定义配置数据(常量) |
| 52 | + │ |
| 53 | + ├─about |
| 54 | + │ AboutActivity.java |
| 55 | + │ |
| 56 | + ├─appwidget |
| 57 | + │ ScheduleWidgetProvider.java |
| 58 | + │ ScheduleWidgetRemoteViewsService.java |
| 59 | + │ |
| 60 | + ├─debug |
| 61 | + │ │ DebugAction.java |
| 62 | + │ │ DebugActivity.java |
| 63 | + │ │ DebugFragment.java |
| 64 | + │ │ |
| 65 | + │ └─actions |
| 66 | + │ DisplayUserDataDebugAction.java |
| 67 | + │ ForceAppDataSyncNowAction.java |
| 68 | + │ ForceSyncNowAction.java |
| 69 | + │ ... |
| 70 | + │ |
| 71 | + ├─explore |
| 72 | + │ │ ExploreIOActivity.java |
| 73 | + │ │ ExploreIOFragment.java |
| 74 | + │ │ ExploreModel.java |
| 75 | + │ │ ... |
| 76 | + │ │ |
| 77 | + │ └─data |
| 78 | + │ ItemGroup.java |
| 79 | + │ LiveStreamData.java |
| 80 | + │ MessageData.java |
| 81 | + │ ... |
| 82 | + │ |
| 83 | + ├─feedback |
| 84 | + │ FeedbackApiHelper.java |
| 85 | + │ FeedbackConstants.java |
| 86 | + │ FeedbackHelper.java |
| 87 | + │ ... |
| 88 | + │ |
| 89 | + ├─framework |
| 90 | + │ FragmentListener.java |
| 91 | + │ LoaderIdlingResource.java |
| 92 | + │ Model.java |
| 93 | + │ ...定义interface并实现 |
| 94 | + │ |
| 95 | + ├─gcm |
| 96 | + │ │ GCMCommand.java |
| 97 | + │ │ GCMIntentService.java |
| 98 | + │ │ GCMRedirectedBroadcastReceiver.java |
| 99 | + │ │ ... |
| 100 | + │ │ |
| 101 | + │ └─command |
| 102 | + │ AnnouncementCommand.java |
| 103 | + │ NotificationCommand.java |
| 104 | + │ SyncCommand.java |
| 105 | + │ ... |
| 106 | + │ |
| 107 | + ├─io |
| 108 | + │ │ BlocksHandler.java |
| 109 | + │ │ HandlerException.java |
| 110 | + │ │ HashtagsHandler.java |
| 111 | + │ │ ...处理model |
| 112 | + │ │ |
| 113 | + │ ├─map |
| 114 | + │ │ └─model |
| 115 | + │ │ MapData.java |
| 116 | + │ │ Marker.java |
| 117 | + │ │ Tile.java |
| 118 | + │ │ |
| 119 | + │ └─model |
| 120 | + │ Block.java |
| 121 | + │ DataManifest.java |
| 122 | + │ Hashtag.java |
| 123 | + │ ... |
| 124 | + │ |
| 125 | + ├─map |
| 126 | + │ │ InlineInfoFragment.java |
| 127 | + │ │ MapActivity.java |
| 128 | + │ │ MapFragment.java |
| 129 | + │ │ ... |
| 130 | + │ │ |
| 131 | + │ └─util |
| 132 | + │ CachedTileProvider.java |
| 133 | + │ MarkerLoadingTask.java |
| 134 | + │ MarkerModel.java |
| 135 | + │ ... |
| 136 | + │ |
| 137 | + ├─model |
| 138 | + │ ScheduleHelper.java |
| 139 | + │ ScheduleItem.java |
| 140 | + │ ScheduleItemHelper.java |
| 141 | + │ ...定义model以及实现model相关操作 |
| 142 | + │ |
| 143 | + ├─myschedule |
| 144 | + │ MyScheduleActivity.java |
| 145 | + │ MyScheduleAdapter.java |
| 146 | + │ MyScheduleFragment.java |
| 147 | + │ ... |
| 148 | + │ |
| 149 | + ├─provider |
| 150 | + │ ScheduleContract.java |
| 151 | + │ ScheduleContractHelper.java |
| 152 | + │ ScheduleDatabase.java |
| 153 | + │ ...实现ContentProvider |
| 154 | + │ (也在此处定义provider依赖的其它类,比如db操作) |
| 155 | + │ |
| 156 | + ├─receiver |
| 157 | + │ SessionAlarmReceiver.java |
| 158 | + │ |
| 159 | + ├─service |
| 160 | + │ DataBootstrapService.java |
| 161 | + │ SessionAlarmService.java |
| 162 | + │ SessionCalendarService.java |
| 163 | + │ |
| 164 | + ├─session |
| 165 | + │ SessionDetailActivity.java |
| 166 | + │ SessionDetailConstants.java |
| 167 | + │ SessionDetailFragment.java |
| 168 | + │ ... |
| 169 | + │ |
| 170 | + ├─settings |
| 171 | + │ ConfMessageCardUtils.java |
| 172 | + │ SettingsActivity.java |
| 173 | + │ SettingsUtils.java |
| 174 | + │ |
| 175 | + ├─social |
| 176 | + │ SocialActivity.java |
| 177 | + │ SocialFragment.java |
| 178 | + │ SocialModel.java |
| 179 | + │ |
| 180 | + ├─sync |
| 181 | + │ │ ConferenceDataHandler.java |
| 182 | + │ │ RemoteConferenceDataFetcher.java |
| 183 | + │ │ SyncAdapter.java |
| 184 | + │ │ ... |
| 185 | + │ │ |
| 186 | + │ └─userdata |
| 187 | + │ │ AbstractUserDataSyncHelper.java |
| 188 | + │ │ OnSuccessListener.java |
| 189 | + │ │ UserAction.java |
| 190 | + │ │ ... |
| 191 | + │ │ |
| 192 | + │ ├─gms |
| 193 | + │ │ DriveHelper.java |
| 194 | + │ │ GMSUserDataSyncHelper.java |
| 195 | + │ │ |
| 196 | + │ └─util |
| 197 | + │ UserActionHelper.java |
| 198 | + │ UserDataHelper.java |
| 199 | + │ |
| 200 | + ├─ui |
| 201 | + │ │ BaseActivity.java |
| 202 | + │ │ CheckableLinearLayout.java |
| 203 | + │ │ SearchActivity.java |
| 204 | + │ │ ...BaseActivity以及自定义UI组件 |
| 205 | + │ │ |
| 206 | + │ └─widget |
| 207 | + │ AspectRatioView.java |
| 208 | + │ BakedBezierInterpolator.java |
| 209 | + │ BezelImageView.java |
| 210 | + │ ...自定义小UI控件 |
| 211 | + │ |
| 212 | + ├─util |
| 213 | + │ AboutUtils.java |
| 214 | + │ AccountUtils.java |
| 215 | + │ AnalyticsHelper.java |
| 216 | + │ ...工具类,提供静态方法 |
| 217 | + │ |
| 218 | + ├─videolibrary |
| 219 | + │ VideoLibraryActivity.java |
| 220 | + │ VideoLibraryFilteredActivity.java |
| 221 | + │ VideoLibraryFilteredFragment.java |
| 222 | + │ ... |
| 223 | + │ |
| 224 | + └─welcome |
| 225 | + AccountFragment.java |
| 226 | + AttendingFragment.java |
| 227 | + ConductFragment.java |
| 228 | + ... |
| 229 | +``` |
| 230 | + |
| 231 | +参考Google I/O 2015的代码结构,按功能分包具体可以这样做: |
| 232 | + |
| 233 | +``` |
| 234 | +src |
| 235 | +└─com |
| 236 | + └─domain |
| 237 | + └─app |
| 238 | + │ AppApplication.java 定义Application类 |
| 239 | + │ Config.java 定义配置数据(常量) |
| 240 | + │ |
| 241 | + ├─framework |
| 242 | + │ 定义interface以及相关基类 |
| 243 | + │ |
| 244 | + ├─io |
| 245 | + │ 数据定义(model)、数据操作(比如json解析,但不包括db操作) |
| 246 | + │ |
| 247 | + ├─model |
| 248 | + │ 定义model(数据结构以及getter/setter、compareTo、equals等等,不含复杂操作) |
| 249 | + │ 以及modelHelper(提供便于操作model的api) |
| 250 | + │ |
| 251 | + ├─provider |
| 252 | + │ 实现ContentProvider,及其依赖的db操作 |
| 253 | + │ |
| 254 | + ├─receiver |
| 255 | + │ 实现Receiver |
| 256 | + │ |
| 257 | + ├─service |
| 258 | + │ 实现Service(比如IntentService),用于在独立线程中异步do stuff |
| 259 | + │ |
| 260 | + ├─ui |
| 261 | + │ 实现BaseActivity,以及自定义view和widget,相关的Adapter也放这里 |
| 262 | + │ |
| 263 | + ├─util |
| 264 | + │ 实现工具类,提供静态方法 |
| 265 | + │ |
| 266 | + ├─feature1 |
| 267 | + │ Item.java 定义model |
| 268 | + │ ItemHelper.java 实现modelHelper |
| 269 | + │ feature1Activity.java 定义UI |
| 270 | + │ feature1DAO.java 私有db操作 |
| 271 | + │ feature1Utils.java 私有工具函数 |
| 272 | + │ ...其它私有class |
| 273 | + │ |
| 274 | + ├─...其它feature |
| 275 | +``` |
| 276 | + |
| 277 | +PBF(按功能分包Package By Feature)与PBL(按层分包Package By Layer)相比较有如下优势: |
| 278 | + |
| 279 | +* package内高内聚,package间低耦合 |
| 280 | + |
| 281 | +哪块要添新功能,只改某一个package下的东西 |
| 282 | + |
| 283 | +按class职能分层(PBL)降低了代码耦合,但带来了package耦合,要添新功能,需要改model、dbHelper、view、service等等,需要改动好几个package下的代码,改动的地方越多,越容易产生新问题,不是吗? |
| 284 | + |
| 285 | +按功能分包(PBF),featureA相关的所有东西都在featureA包,feature内高内聚高度模块化,不同feature之间低耦合,相关的东西都放在一起,还好找 |
| 286 | + |
| 287 | +* package有私有作用域(package-private scope) |
| 288 | + |
| 289 | +你负责开发这块功能,这个目录下所有东西都是你的 |
| 290 | + |
| 291 | +PBL的方式是把所有工具方法都放在util包下,小张开发新功能时候发现需要一个xxUtil,但它又不是通用的,那应该放在哪里?没办法,按照分层原则,我们还得放在util包下,好像不太合适,但放在其它包更不合适,功能越来越多,util类也越定义越多。后来小李负责开发一块功能时发现需要一个xxUtil,同样不通用,去util包一看,怎么已经有了,而且还没法复用,只好放弃xx这个名字,改为xxxUtil……因为PBL的package没有私有作用域,每一个包都是public(跨包方法调用是很平常的事情,每一个包对其它包来说都是可访问的) |
| 292 | + |
| 293 | +如果是PBF,小张的xxUtil自然放在feautreA下,小李的xxUtil在featureB下,如果觉得util好像是通用的,就去util包看看要不要把工具方法添进xxUtil,class命名冲突没有了 |
| 294 | + |
| 295 | +PBF的package有私有作用域,featureA不应该访问featureB下的任何东西(如果非访问不可,那就说明接口定义有问题) |
| 296 | + |
| 297 | +* 很容易删除功能 |
| 298 | + |
| 299 | +统计发现新功能没人用,这个版本那块功能得去掉 |
| 300 | + |
| 301 | +如果是PBL,得从功能入口到整个业务流程把受到牵连的所有能删的代码和class都揪出来删掉,一不小心就完蛋 |
| 302 | + |
| 303 | +如果是PBF,好说,先删掉对应包,再删掉功能入口(删掉包后入口肯定报错了),完事 |
| 304 | + |
| 305 | +* 高度抽象 |
| 306 | + |
| 307 | +解决问题的一般方法是从抽象到具体,PBF包名是对功能模块的抽象,包内的class是实现细节,符合从抽象到具体,而PBL弄反了 |
| 308 | + |
| 309 | +PBF从确定AppName开始,根据功能模块划分package,再考虑每块的具体实现细节,而PBL从一开始就要考虑要不要dao层,要不要com层等等 |
| 310 | + |
| 311 | +* 只通过class来分离逻辑代码 |
| 312 | + |
| 313 | +PBL既分离class又分离package,而PBF只通过class来分离逻辑代码 |
| 314 | + |
| 315 | +没有必要通过package分离,因为PBL中也可能出现尴尬的情况: |
| 316 | + |
| 317 | +``` |
| 318 | +├─service |
| 319 | + │ MainServ.java |
| 320 | +``` |
| 321 | + |
| 322 | +按照PBL,service包下的所有东西都是Controller,应该不需要Serv后缀,但实际上通常为了码起来方便,直接import service包,Serv后缀是为了避免引入的class和当前包下的class命名冲突,当然,不用后缀也可以,得写清楚包路径,比如new net.ayqy.service.Main(),麻烦 |
| 323 | + |
| 324 | +而PBF就很方便,无需import,直接new MainServ()即可 |
44 | 325 |
|
45 |
| -| 包名 | 此包中包含 | |
46 |
| -| :--------------------------------------- | :----------------------------- | |
47 |
| -| com.xx.应用名称缩写.activity | 用户界面中所有的Activity类 | |
48 |
| -| com.xx.应用名称缩写.fragment | 界面中所有的Fragment类 | |
49 |
| -| com.xx.应用名称缩写.base | 基础共享的类 | |
50 |
| -| com.xx.应用名称缩写.adapter | 页面用到的Adapter类 (适配器的类) | |
51 |
| -| com.xx.应用名称缩写.view | 自定义的View类 | |
52 |
| -| com.xx.应用名称缩写.util | 此包中包含:公共工具方法类(util模块名) | |
53 |
| -| com.xx.应用名称缩写.bean | 下面可分:vo、po、dto 此包中包含:JavaBean类 | |
54 |
| -| com.xx.应用名称缩写.model | 此包中包含:模型类 | |
55 |
| -| com.xx.应用名称缩写.db | 数据库操作类 | |
56 |
| -| com.xx.应用名称缩写.view (或者 com.xx.应用名称缩写.widget ) | 自定义的View类等 | |
57 |
| -| com.xx.应用名称缩写.service | Service服务 | |
58 |
| -| com.xx.应用名称缩写.receiver | BroadcastReceiver服务 | |
59 |
| -| com.xx.应用名称缩写.config | 所有的配置相关的类 | |
| 326 | +* package的大小有意义了 |
60 | 327 |
|
61 |
| -> 注意:如果项目采用MVP,所有M、V、P抽取出来的接口都放置在相应模块的i包下,所有的实现都放置在相应模块的impl下 |
| 328 | +PBL中包的大小无限增长是合理的,因为功能越添越多 |
62 | 329 |
|
| 330 | +而PBF中包太大(包里class太多)表示这块需要重构(划分子包) |
63 | 331 |
|
64 | 332 | #### 3.2 类名
|
65 | 333 |
|
@@ -755,9 +1023,13 @@ AS已帮你集成了一些注释模板,我们只需要直接使用即可,在
|
755 | 1023 | * 17/03/06: 发布初版 ;
|
756 | 1024 | * 17/03/07: 修订目录排版,完善某些细节;
|
757 | 1025 | * 17/03/08: 规范排版,修复typor及新增一些规范;
|
| 1026 | +* 17/03/13: 新增其他注释; |
| 1027 | +* 17/03/14: 包名划分为按功能划分; |
758 | 1028 |
|
759 | 1029 | ——powered by Blankj(蔡梦杰)
|
760 | 1030 |
|
| 1031 | +[Package by features, not layers]: https://medium.com/@cesarmcferreira/package-by-features-not-layers-2d076df1964d#.mp782izhh |
| 1032 | +[iosched]: https://github.com/google/iosched/tree/master/android/src/main/java/com/google/samples/apps/iosched |
761 | 1033 | [安卓开发规范(updating)]: https://github.com/Blankj/AndroidStandardDevelop
|
762 | 1034 | [AS常用开发插件]: http://www.jianshu.com/p/c76b0d8a642d
|
763 | 1035 | [Android Studio下对资源进行分包]: http://www.jianshu.com/p/8e893581b9c7
|
|
0 commit comments