├── LICENSE ├── README.md ├── architecture_guidelines ├── android_architecture.md └── architecture_diagram.png └── project_and_code_guidelines.md /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 Ribot Ltd. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Thank you for your interest in ribot’s development work. Unfortunately there are no current plans to make any changes to this project in the near future, and it is not being maintained or updated. We hope you still find this a useful resource and you can check out the newest recommendations in [Android Jetpack](https://developer.android.com/jetpack/) for more ideas! 2 | 3 | # Android Guidelines 4 | 5 | List of guidelines that we use at [ribot](http://ribot.co.uk) when developing for the __Android__ platform. 6 | 7 | * [Project and code style guidelines](project_and_code_guidelines.md) 8 | * [Architecture Guidelines](architecture_guidelines/android_architecture.md) 9 | 10 | ### License 11 | 12 | ``` 13 | Copyright 2015 Ribot Ltd. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | Unless required by applicable law or agreed to in writing, software 22 | distributed under the License is distributed on an "AS IS" BASIS, 23 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | See the License for the specific language governing permissions and 25 | limitations under the License. 26 | ``` -------------------------------------------------------------------------------- /architecture_guidelines/android_architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture Guidelines 2 | 3 | The architecture of our Android apps is based on the [MVP](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter) (Model View Presenter) pattern. 4 | 5 | * __View (UI layer)__: this is where Activities, Fragments and other standard Android components live. It's responsible for displaying the data received from the presenters to the user. It also handles user interactions and inputs (click listeners, etc) and triggers the right action in the Presenter if needed. 6 | 7 | * __Presenter__: presenters subscribe to RxJava Observables provided by the `DataManager`. They are in charge of handling the subscription lifecycle, analysing/modifying the data returned by the `DataManager` and calling the appropriate methods in the View in order to display the data. 8 | 9 | * __Model (Data Layer)__: this is responsible for retrieving, saving, caching and massaging data. It can communicate with local databases and other data stores as well as with restful APIs or third party SDKs. It is divided in two parts: a group of helpers and a `DataManager`. The number of helpers vary between project and each of them has a very specific function, e.g. talking to an API or saving data in `SharedPreferences`. The `DataManager` combines and transforms the outputs from different helpers using Rx operators so it can: 1) provide meaningful data to the Presenter, 2) group actions that will always happen together. This layer also contains the actual model classes that define how the data structure is. 10 | 11 | ![](architecture_diagram.png) 12 | 13 | Looking at the diagram from right to left: 14 | 15 | * __Helpers (Model)__: A set of classes, each of them with a very specific responsibility. Their function can range from talking to APIs or a database to implementing some specific business logic. Every project will have different helpers but the most common ones are: 16 | - __DatabaseHelper__: It handles inserting, updating and retrieving data from a local SQLite database. Its methods return Rx Observables that emit plain java objects (models) 17 | - __PreferencesHelper__: It saves and gets data from `SharedPreferences`, it can return Observables or plain java objects directly. 18 | - __Retrofit services__ : [Retrofit](http://square.github.io/retrofit) interfaces that talk to Restful APIs, each different API will have its own Retrofit service. They return Rx Observables. 19 | 20 | * __Data Manager (Model)__: It's a key part of the architecture. It keeps a reference to every helper class and uses them to satisfy the requests coming from the presenters. Its methods make extensive use of Rx operators to combine, transform or filter the output coming from the helpers in order to generate the desired output ready for the Presenters. It returns observables that emit data models. 21 | 22 | * __Presenters__: Subscribe to observables provided by the `DataManager` and process the data in order to call the right method in the View. 23 | 24 | * __Activities, Fragments, ViewGroups (View)__: Standard Android components that implement a set of methods that the Presenters can call. They also handle user interactions such as clicks and act accordingly by calling the appropriate method in the Presenter. These components also implement framework-related tasks such us managing the Android lifecycle, inflating views, etc. 25 | 26 | * __Event Bus__: It allows the View components to be notified of certain types of events that happen in the Model. Generally the `DataManager` posts events which can then be subscribed to by Activities and Fragments. The event bus is __only used for very specific actions__ that are not related to only one screen and have a broadcasting nature, e.g. the user has signed out. 27 | 28 | # License 29 | 30 | ``` 31 | Copyright 2015 Ribot Ltd. 32 | 33 | Licensed under the Apache License, Version 2.0 (the "License"); 34 | you may not use this file except in compliance with the License. 35 | You may obtain a copy of the License at 36 | 37 | http://www.apache.org/licenses/LICENSE-2.0 38 | 39 | Unless required by applicable law or agreed to in writing, software 40 | distributed under the License is distributed on an "AS IS" BASIS, 41 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 42 | See the License for the specific language governing permissions and 43 | limitations under the License. 44 | ``` -------------------------------------------------------------------------------- /architecture_guidelines/architecture_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ribot/android-guidelines/c2f28b2b567d0e4068308f2d9b7f147b092be56b/architecture_guidelines/architecture_diagram.png -------------------------------------------------------------------------------- /project_and_code_guidelines.md: -------------------------------------------------------------------------------- 1 | # 1. Project guidelines 2 | 3 | ## 1.1 Project structure 4 | 5 | New projects should follow the Android Gradle project structure that is defined on the [Android Gradle plugin user guide](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Project-Structure). The [ribot Boilerplate](https://github.com/ribot/android-boilerplate) project is a good reference to start from. 6 | 7 | ## 1.2 File naming 8 | 9 | ### 1.2.1 Class files 10 | Class names are written in [UpperCamelCase](http://en.wikipedia.org/wiki/CamelCase). 11 | 12 | For classes that extend an Android component, the name of the class should end with the name of the component; for example: `SignInActivity`, `SignInFragment`, `ImageUploaderService`, `ChangePasswordDialog`. 13 | 14 | ### 1.2.2 Resources files 15 | 16 | Resources file names are written in __lowercase_underscore__. 17 | 18 | #### 1.2.2.1 Drawable files 19 | 20 | Naming conventions for drawables: 21 | 22 | 23 | | Asset Type | Prefix | Example | 24 | |--------------| ------------------|-----------------------------| 25 | | Action bar | `ab_` | `ab_stacked.9.png` | 26 | | Button | `btn_` | `btn_send_pressed.9.png` | 27 | | Dialog | `dialog_` | `dialog_top.9.png` | 28 | | Divider | `divider_` | `divider_horizontal.9.png` | 29 | | Icon | `ic_` | `ic_star.png` | 30 | | Menu | `menu_ ` | `menu_submenu_bg.9.png` | 31 | | Notification | `notification_` | `notification_bg.9.png` | 32 | | Tabs | `tab_` | `tab_pressed.9.png` | 33 | 34 | Naming conventions for icons (taken from [Android iconography guidelines](http://developer.android.com/design/style/iconography.html)): 35 | 36 | | Asset Type | Prefix | Example | 37 | | --------------------------------| ---------------- | ---------------------------- | 38 | | Icons | `ic_` | `ic_star.png` | 39 | | Launcher icons | `ic_launcher` | `ic_launcher_calendar.png` | 40 | | Menu icons and Action Bar icons | `ic_menu` | `ic_menu_archive.png` | 41 | | Status bar icons | `ic_stat_notify` | `ic_stat_notify_msg.png` | 42 | | Tab icons | `ic_tab` | `ic_tab_recent.png` | 43 | | Dialog icons | `ic_dialog` | `ic_dialog_info.png` | 44 | 45 | Naming conventions for selector states: 46 | 47 | | State | Suffix | Example | 48 | |--------------|-----------------|-----------------------------| 49 | | Normal | `_normal` | `btn_order_normal.9.png` | 50 | | Pressed | `_pressed` | `btn_order_pressed.9.png` | 51 | | Focused | `_focused` | `btn_order_focused.9.png` | 52 | | Disabled | `_disabled` | `btn_order_disabled.9.png` | 53 | | Selected | `_selected` | `btn_order_selected.9.png` | 54 | 55 | 56 | #### 1.2.2.2 Layout files 57 | 58 | Layout files should match the name of the Android components that they are intended for but moving the top level component name to the beginning. For example, if we are creating a layout for the `SignInActivity`, the name of the layout file should be `activity_sign_in.xml`. 59 | 60 | | Component | Class Name | Layout Name | 61 | | ---------------- | ---------------------- | ----------------------------- | 62 | | Activity | `UserProfileActivity` | `activity_user_profile.xml` | 63 | | Fragment | `SignUpFragment` | `fragment_sign_up.xml` | 64 | | Dialog | `ChangePasswordDialog` | `dialog_change_password.xml` | 65 | | AdapterView item | --- | `item_person.xml` | 66 | | Partial layout | --- | `partial_stats_bar.xml` | 67 | 68 | A slightly different case is when we are creating a layout that is going to be inflated by an `Adapter`, e.g to populate a `ListView`. In this case, the name of the layout should start with `item_`. 69 | 70 | Note that there are cases where these rules will not be possible to apply. For example, when creating layout files that are intended to be part of other layouts. In this case you should use the prefix `partial_`. 71 | 72 | #### 1.2.2.3 Menu files 73 | 74 | Similar to layout files, menu files should match the name of the component. For example, if we are defining a menu file that is going to be used in the `UserActivity`, then the name of the file should be `activity_user.xml` 75 | 76 | A good practice is to not include the word `menu` as part of the name because these files are already located in the `menu` directory. 77 | 78 | #### 1.2.2.4 Values files 79 | 80 | Resource files in the values folder should be __plural__, e.g. `strings.xml`, `styles.xml`, `colors.xml`, `dimens.xml`, `attrs.xml` 81 | 82 | # 2 Code guidelines 83 | 84 | ## 2.1 Java language rules 85 | 86 | ### 2.1.1 Don't ignore exceptions 87 | 88 | You must never do the following: 89 | 90 | ```java 91 | void setServerPort(String value) { 92 | try { 93 | serverPort = Integer.parseInt(value); 94 | } catch (NumberFormatException e) { } 95 | } 96 | ``` 97 | 98 | _While you may think that your code will never encounter this error condition or that it is not important to handle it, ignoring exceptions like above creates mines in your code for someone else to trip over some day. You must handle every Exception in your code in some principled way. The specific handling varies depending on the case._ - ([Android code style guidelines](https://source.android.com/source/code-style.html)) 99 | 100 | See alternatives [here](https://source.android.com/source/code-style.html#dont-ignore-exceptions). 101 | 102 | ### 2.1.2 Don't catch generic exception 103 | 104 | You should not do this: 105 | 106 | ```java 107 | try { 108 | someComplicatedIOFunction(); // may throw IOException 109 | someComplicatedParsingFunction(); // may throw ParsingException 110 | someComplicatedSecurityFunction(); // may throw SecurityException 111 | // phew, made it all the way 112 | } catch (Exception e) { // I'll just catch all exceptions 113 | handleError(); // with one generic handler! 114 | } 115 | ``` 116 | 117 | See the reason why and some alternatives [here](https://source.android.com/source/code-style.html#dont-catch-generic-exception) 118 | 119 | ### 2.1.3 Don't use finalizers 120 | 121 | _We don't use finalizers. There are no guarantees as to when a finalizer will be called, or even that it will be called at all. In most cases, you can do what you need from a finalizer with good exception handling. If you absolutely need it, define a `close()` method (or the like) and document exactly when that method needs to be called. See `InputStream` for an example. In this case it is appropriate but not required to print a short log message from the finalizer, as long as it is not expected to flood the logs._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#dont-use-finalizers)) 122 | 123 | 124 | ### 2.1.4 Fully qualify imports 125 | 126 | This is bad: `import foo.*;` 127 | 128 | This is good: `import foo.Bar;` 129 | 130 | See more info [here](https://source.android.com/source/code-style.html#fully-qualify-imports) 131 | 132 | ## 2.2 Java style rules 133 | 134 | ### 2.2.1 Fields definition and naming 135 | 136 | Fields should be defined at the __top of the file__ and they should follow the naming rules listed below. 137 | 138 | * Private, non-static field names start with __m__. 139 | * Private, static field names start with __s__. 140 | * Other fields start with a lower case letter. 141 | * Static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES. 142 | 143 | Example: 144 | 145 | ```java 146 | public class MyClass { 147 | public static final int SOME_CONSTANT = 42; 148 | public int publicField; 149 | private static MyClass sSingleton; 150 | int mPackagePrivate; 151 | private int mPrivate; 152 | protected int mProtected; 153 | } 154 | ``` 155 | 156 | ### 2.2.3 Treat acronyms as words 157 | 158 | | Good | Bad | 159 | | -------------- | -------------- | 160 | | `XmlHttpRequest` | `XMLHTTPRequest` | 161 | | `getCustomerId` | `getCustomerID` | 162 | | `String url` | `String URL` | 163 | | `long id` | `long ID` | 164 | 165 | ### 2.2.4 Use spaces for indentation 166 | 167 | Use __4 space__ indents for blocks: 168 | 169 | ```java 170 | if (x == 1) { 171 | x++; 172 | } 173 | ``` 174 | 175 | Use __8 space__ indents for line wraps: 176 | 177 | ```java 178 | Instrument i = 179 | someLongExpression(that, wouldNotFit, on, one, line); 180 | ``` 181 | 182 | ### 2.2.5 Use standard brace style 183 | 184 | Braces go on the same line as the code before them. 185 | 186 | ```java 187 | class MyClass { 188 | int func() { 189 | if (something) { 190 | // ... 191 | } else if (somethingElse) { 192 | // ... 193 | } else { 194 | // ... 195 | } 196 | } 197 | } 198 | ``` 199 | 200 | Braces around the statements are required unless the condition and the body fit on one line. 201 | 202 | If the condition and the body fit on one line and that line is shorter than the max line length, then braces are not required, e.g. 203 | 204 | ```java 205 | if (condition) body(); 206 | ``` 207 | 208 | This is __bad__: 209 | 210 | ```java 211 | if (condition) 212 | body(); // bad! 213 | ``` 214 | 215 | ### 2.2.6 Annotations 216 | 217 | #### 2.2.6.1 Annotations practices 218 | 219 | According to the Android code style guide, the standard practices for some of the predefined annotations in Java are: 220 | 221 | * `@Override`: The @Override annotation __must be used__ whenever a method overrides the declaration or implementation from a super-class. For example, if you use the @inheritdocs Javadoc tag, and derive from a class (not an interface), you must also annotate that the method @Overrides the parent class's method. 222 | 223 | * `@SuppressWarnings`: The @SuppressWarnings annotation should only be used under circumstances where it is impossible to eliminate a warning. If a warning passes this "impossible to eliminate" test, the @SuppressWarnings annotation must be used, so as to ensure that all warnings reflect actual problems in the code. 224 | 225 | More information about annotation guidelines can be found [here](http://source.android.com/source/code-style.html#use-standard-java-annotations). 226 | 227 | #### 2.2.6.2 Annotations style 228 | 229 | __Classes, Methods and Constructors__ 230 | 231 | When annotations are applied to a class, method, or constructor, they are listed after the documentation block and should appear as __one annotation per line__ . 232 | 233 | ```java 234 | /* This is the documentation block about the class */ 235 | @AnnotationA 236 | @AnnotationB 237 | public class MyAnnotatedClass { } 238 | ``` 239 | 240 | __Fields__ 241 | 242 | Annotations applying to fields should be listed __on the same line__, unless the line reaches the maximum line length. 243 | 244 | ```java 245 | @Nullable @Mock DataManager mDataManager; 246 | ``` 247 | 248 | ### 2.2.7 Limit variable scope 249 | 250 | _The scope of local variables should be kept to a minimum (Effective Java Item 29). By doing so, you increase the readability and maintainability of your code and reduce the likelihood of error. Each variable should be declared in the innermost block that encloses all uses of the variable._ 251 | 252 | _Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration until you do._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#limit-variable-scope)) 253 | 254 | ### 2.2.8 Order import statements 255 | 256 | If you are using an IDE such as Android Studio, you don't have to worry about this because your IDE is already obeying these rules. If not, have a look below. 257 | 258 | The ordering of import statements is: 259 | 260 | 1. Android imports 261 | 2. Imports from third parties (com, junit, net, org) 262 | 3. java and javax 263 | 4. Same project imports 264 | 265 | To exactly match the IDE settings, the imports should be: 266 | 267 | * Alphabetically ordered within each grouping, with capital letters before lower case letters (e.g. Z before a). 268 | * There should be a blank line between each major grouping (android, com, junit, net, org, java, javax). 269 | 270 | More info [here](https://source.android.com/source/code-style.html#limit-variable-scope) 271 | 272 | ### 2.2.9 Logging guidelines 273 | 274 | Use the logging methods provided by the `Log` class to print out error messages or other information that may be useful for developers to identify issues: 275 | 276 | * `Log.v(String tag, String msg)` (verbose) 277 | * `Log.d(String tag, String msg)` (debug) 278 | * `Log.i(String tag, String msg)` (information) 279 | * `Log.w(String tag, String msg)` (warning) 280 | * `Log.e(String tag, String msg)` (error) 281 | 282 | As a general rule, we use the class name as tag and we define it as a `static final` field at the top of the file. For example: 283 | 284 | ```java 285 | public class MyClass { 286 | private static final String TAG = MyClass.class.getSimpleName(); 287 | 288 | public myMethod() { 289 | Log.e(TAG, "My error message"); 290 | } 291 | } 292 | ``` 293 | 294 | VERBOSE and DEBUG logs __must__ be disabled on release builds. It is also recommended to disable INFORMATION, WARNING and ERROR logs but you may want to keep them enabled if you think they may be useful to identify issues on release builds. If you decide to leave them enabled, you have to make sure that they are not leaking private information such as email addresses, user ids, etc. 295 | 296 | To only show logs on debug builds: 297 | 298 | ```java 299 | if (BuildConfig.DEBUG) Log.d(TAG, "The value of x is " + x); 300 | ``` 301 | 302 | ### 2.2.10 Class member ordering 303 | 304 | There is no single correct solution for this but using a __logical__ and __consistent__ order will improve code learnability and readability. It is recommendable to use the following order: 305 | 306 | 1. Constants 307 | 2. Fields 308 | 3. Constructors 309 | 4. Override methods and callbacks (public or private) 310 | 5. Public methods 311 | 6. Private methods 312 | 7. Inner classes or interfaces 313 | 314 | Example: 315 | 316 | ```java 317 | public class MainActivity extends Activity { 318 | 319 | private static final String TAG = MainActivity.class.getSimpleName(); 320 | 321 | private String mTitle; 322 | private TextView mTextViewTitle; 323 | 324 | @Override 325 | public void onCreate() { 326 | ... 327 | } 328 | 329 | public void setTitle(String title) { 330 | mTitle = title; 331 | } 332 | 333 | private void setUpView() { 334 | ... 335 | } 336 | 337 | static class AnInnerClass { 338 | 339 | } 340 | 341 | } 342 | ``` 343 | 344 | If your class is extending an __Android component__ such as an Activity or a Fragment, it is a good practice to order the override methods so that they __match the component's lifecycle__. For example, if you have an Activity that implements `onCreate()`, `onDestroy()`, `onPause()` and `onResume()`, then the correct order is: 345 | 346 | ```java 347 | public class MainActivity extends Activity { 348 | 349 | //Order matches Activity lifecycle 350 | @Override 351 | public void onCreate() {} 352 | 353 | @Override 354 | public void onResume() {} 355 | 356 | @Override 357 | public void onPause() {} 358 | 359 | @Override 360 | public void onDestroy() {} 361 | 362 | } 363 | ``` 364 | 365 | ### 2.2.11 Parameter ordering in methods 366 | 367 | When programming for Android, it is quite common to define methods that take a `Context`. If you are writing a method like this, then the __Context__ must be the __first__ parameter. 368 | 369 | The opposite case are __callback__ interfaces that should always be the __last__ parameter. 370 | 371 | Examples: 372 | 373 | ```java 374 | // Context always goes first 375 | public User loadUser(Context context, int userId); 376 | 377 | // Callbacks always go last 378 | public void loadUserAsync(Context context, int userId, UserCallback callback); 379 | ``` 380 | 381 | ### 2.2.13 String constants, naming, and values 382 | 383 | Many elements of the Android SDK such as `SharedPreferences`, `Bundle`, or `Intent` use a key-value pair approach so it's very likely that even for a small app you end up having to write a lot of String constants. 384 | 385 | When using one of these components, you __must__ define the keys as a `static final` fields and they should be prefixed as indicated below. 386 | 387 | | Element | Field Name Prefix | 388 | | ----------------- | ----------------- | 389 | | SharedPreferences | `PREF_` | 390 | | Bundle | `BUNDLE_` | 391 | | Fragment Arguments | `ARGUMENT_` | 392 | | Intent Extra | `EXTRA_` | 393 | | Intent Action | `ACTION_` | 394 | 395 | Note that the arguments of a Fragment - `Fragment.getArguments()` - are also a Bundle. However, because this is a quite common use of Bundles, we define a different prefix for them. 396 | 397 | Example: 398 | 399 | ```java 400 | // Note the value of the field is the same as the name to avoid duplication issues 401 | static final String PREF_EMAIL = "PREF_EMAIL"; 402 | static final String BUNDLE_AGE = "BUNDLE_AGE"; 403 | static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID"; 404 | 405 | // Intent-related items use full package name as value 406 | static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME"; 407 | static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER"; 408 | ``` 409 | 410 | ### 2.2.14 Arguments in Fragments and Activities 411 | 412 | When data is passed into an `Activity` or `Fragment` via an `Intent` or a `Bundle`, the keys for the different values __must__ follow the rules described in the section above. 413 | 414 | When an `Activity` or `Fragment` expects arguments, it should provide a `public static` method that facilitates the creation of the relevant `Intent` or `Fragment`. 415 | 416 | In the case of Activities the method is usually called `getStartIntent()`: 417 | 418 | ```java 419 | public static Intent getStartIntent(Context context, User user) { 420 | Intent intent = new Intent(context, ThisActivity.class); 421 | intent.putParcelableExtra(EXTRA_USER, user); 422 | return intent; 423 | } 424 | ``` 425 | 426 | For Fragments it is named `newInstance()` and handles the creation of the Fragment with the right arguments: 427 | 428 | ```java 429 | public static UserFragment newInstance(User user) { 430 | UserFragment fragment = new UserFragment(); 431 | Bundle args = new Bundle(); 432 | args.putParcelable(ARGUMENT_USER, user); 433 | fragment.setArguments(args) 434 | return fragment; 435 | } 436 | ``` 437 | 438 | __Note 1__: These methods should go at the top of the class before `onCreate()`. 439 | 440 | __Note 2__: If we provide the methods described above, the keys for extras and arguments should be `private` because there is not need for them to be exposed outside the class. 441 | 442 | ### 2.2.15 Line length limit 443 | 444 | Code lines should not exceed __100 characters__. If the line is longer than this limit there are usually two options to reduce its length: 445 | 446 | * Extract a local variable or method (preferable). 447 | * Apply line-wrapping to divide a single line into multiple ones. 448 | 449 | There are two __exceptions__ where it is possible to have lines longer than 100: 450 | 451 | * Lines that are not possible to split, e.g. long URLs in comments. 452 | * `package` and `import` statements. 453 | 454 | #### 2.2.15.1 Line-wrapping strategies 455 | 456 | There isn't an exact formula that explains how to line-wrap and quite often different solutions are valid. However there are a few rules that can be applied to common cases. 457 | 458 | __Break at operators__ 459 | 460 | When the line is broken at an operator, the break comes __before__ the operator. For example: 461 | 462 | ```java 463 | int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne 464 | + theFinalOne; 465 | ``` 466 | 467 | __Assignment Operator Exception__ 468 | 469 | An exception to the `break at operators` rule is the assignment operator `=`, where the line break should happen __after__ the operator. 470 | 471 | ```java 472 | int longName = 473 | anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne; 474 | ``` 475 | 476 | __Method chain case__ 477 | 478 | When multiple methods are chained in the same line - for example when using Builders - every call to a method should go in its own line, breaking the line before the `.` 479 | 480 | ```java 481 | Picasso.with(context).load("http://ribot.co.uk/images/sexyjoe.jpg").into(imageView); 482 | ``` 483 | 484 | ```java 485 | Picasso.with(context) 486 | .load("http://ribot.co.uk/images/sexyjoe.jpg") 487 | .into(imageView); 488 | ``` 489 | 490 | __Long parameters case__ 491 | 492 | When a method has many parameters or its parameters are very long, we should break the line after every comma `,` 493 | 494 | ```java 495 | loadPicture(context, "http://ribot.co.uk/images/sexyjoe.jpg", mImageViewProfilePicture, clickListener, "Title of the picture"); 496 | ``` 497 | 498 | ```java 499 | loadPicture(context, 500 | "http://ribot.co.uk/images/sexyjoe.jpg", 501 | mImageViewProfilePicture, 502 | clickListener, 503 | "Title of the picture"); 504 | ``` 505 | 506 | ### 2.2.16 RxJava chains styling 507 | 508 | Rx chains of operators require line-wrapping. Every operator must go in a new line and the line should be broken before the `.` 509 | 510 | ```java 511 | public Observable syncLocations() { 512 | return mDatabaseHelper.getAllLocations() 513 | .concatMap(new Func1>() { 514 | @Override 515 | public Observable call(Location location) { 516 | return mRetrofitService.getLocation(location.id); 517 | } 518 | }) 519 | .retry(new Func2() { 520 | @Override 521 | public Boolean call(Integer numRetries, Throwable throwable) { 522 | return throwable instanceof RetrofitError; 523 | } 524 | }); 525 | } 526 | ``` 527 | 528 | ## 2.3 XML style rules 529 | 530 | ### 2.3.1 Use self closing tags 531 | 532 | When an XML element doesn't have any contents, you __must__ use self closing tags. 533 | 534 | This is good: 535 | 536 | ```xml 537 | 541 | ``` 542 | 543 | This is __bad__ : 544 | 545 | ```xml 546 | 547 | 551 | 552 | ``` 553 | 554 | 555 | ### 2.3.2 Resources naming 556 | 557 | Resource IDs and names are written in __lowercase_underscore__. 558 | 559 | #### 2.3.2.1 ID naming 560 | 561 | IDs should be prefixed with the name of the element in lowercase underscore. For example: 562 | 563 | 564 | | Element | Prefix | 565 | | ----------------- | ----------------- | 566 | | `TextView` | `text_` | 567 | | `ImageView` | `image_` | 568 | | `Button` | `button_` | 569 | | `Menu` | `menu_` | 570 | 571 | Image view example: 572 | 573 | ```xml 574 | 578 | ``` 579 | 580 | Menu example: 581 | 582 | ```xml 583 | 584 | 587 | 588 | ``` 589 | 590 | #### 2.3.2.2 Strings 591 | 592 | String names start with a prefix that identifies the section they belong to. For example `registration_email_hint` or `registration_name_hint`. If a string __doesn't belong__ to any section, then you should follow the rules below: 593 | 594 | 595 | | Prefix | Description | 596 | | ----------------- | --------------------------------------| 597 | | `error_` | An error message | 598 | | `msg_` | A regular information message | 599 | | `title_` | A title, i.e. a dialog title | 600 | | `action_` | An action such as "Save" or "Create" | 601 | 602 | 603 | 604 | #### 2.3.2.3 Styles and Themes 605 | 606 | Unlike the rest of resources, style names are written in __UpperCamelCase__. 607 | 608 | ### 2.3.3 Attributes ordering 609 | 610 | As a general rule you should try to group similar attributes together. A good way of ordering the most common attributes is: 611 | 612 | 1. View Id 613 | 2. Style 614 | 3. Layout width and layout height 615 | 4. Other layout attributes, sorted alphabetically 616 | 5. Remaining attributes, sorted alphabetically 617 | 618 | ## 2.4 Tests style rules 619 | 620 | ### 2.4.1 Unit tests 621 | 622 | Test classes should match the name of the class the tests are targeting, followed by `Test`. For example, if we create a test class that contains tests for the `DatabaseHelper`, we should name it `DatabaseHelperTest`. 623 | 624 | Test methods are annotated with `@Test` and should generally start with the name of the method that is being tested, followed by a precondition and/or expected behaviour. 625 | 626 | * Template: `@Test void methodNamePreconditionExpectedBehaviour()` 627 | * Example: `@Test void signInWithEmptyEmailFails()` 628 | 629 | Precondition and/or expected behaviour may not always be required if the test is clear enough without them. 630 | 631 | Sometimes a class may contain a large amount of methods, that at the same time require several tests for each method. In this case, it's recommendable to split up the test class into multiple ones. For example, if the `DataManager` contains a lot of methods we may want to divide it into `DataManagerSignInTest`, `DataManagerLoadUsersTest`, etc. Generally you will be able to see what tests belong together because they have common [test fixtures](https://en.wikipedia.org/wiki/Test_fixture). 632 | 633 | ### 2.4.2 Espresso tests 634 | 635 | Every Espresso test class usually targets an Activity, therefore the name should match the name of the targeted Activity followed by `Test`, e.g. `SignInActivityTest` 636 | 637 | When using the Espresso API it is a common practice to place chained methods in new lines. 638 | 639 | ```java 640 | onView(withId(R.id.view)) 641 | .perform(scrollTo()) 642 | .check(matches(isDisplayed())) 643 | ``` 644 | 645 | # License 646 | 647 | ``` 648 | Copyright 2015 Ribot Ltd. 649 | 650 | Licensed under the Apache License, Version 2.0 (the "License"); 651 | you may not use this file except in compliance with the License. 652 | You may obtain a copy of the License at 653 | 654 | http://www.apache.org/licenses/LICENSE-2.0 655 | 656 | Unless required by applicable law or agreed to in writing, software 657 | distributed under the License is distributed on an "AS IS" BASIS, 658 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 659 | See the License for the specific language governing permissions and 660 | limitations under the License. 661 | ``` 662 | --------------------------------------------------------------------------------