As a developer, there is a good probability that you have used libraries to make code cleaner and easier to use. In order to attain this we need to follow some basic naming conventions.Starting with layouts.
Layouts
In developing android applications the first step is to create a layout which consists of widgets the application needs. Layout has some widgets and these should be followed with some basic naming conventions.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.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 or Recyclerview. In this case, the name of the layout should start with item_
Class Name | Layout Name |
UserProfileActivity.java | activity_user_profile.xml |
SignUpFragement.java | fragment_sign_up.xml |
LogoutDialog.java | dialog_logout.xml |
AdapterViewItem.java | adapter_item_view.xml |
Strings
String names start with a prefix that identifies the section they belong to. We use <HOW>_<DESCRIPTION> for strings naming. <HOW> to indicate reason of the string will be used & description give any extra information
For Example
Prefix | Description |
error_ | An error message |
msg_ | A regular information message |
title_ | A title, i.e. a dialog title |
action_ | An action such as “Save” or “Create |
Drawables
We use <WHAT>_<DESCRIPTION> for strings naming. <WHAT> is Button,Dialog,Divider,Icon, etc & description give any extra information
Asset Type | Prefix | Example |
Action bar | ab_ | ab_stacked.9.png |
Button | btn_ | btn_send_pressed.9.png |
Dialog | dialog_ | dialog_top.9.png |
Divider | divider_ | divider_horizontal.9.png |
Icon | ic_ | ic_star.png |
Menu | menu_ | menu_submenu_bg.9.png |
Notification | notification_ | notification_bg.9.png |
Tabs | tab_ | tab_pressed.9.png |
Naming conventions for icons
Asset Type | Prefix | Example |
Icons | ic_ | ic_star.png |
Launcher icons | ic_launcher | ic_launcher_calendar.png |
Menu icons and Action Bar icons | ic_menu | ic_menu_archive.png |
Status bar icons | ic_stat_notify | ic_stat_notify_msg.png |
Tab icons | ic_tab | ic_tab_recent.png |
Dialog icons | ic_dialog | ic_dialog_info.png |
Naming conventions for selector states
State | Suffix | Example |
Normal | _normal | btn_order_normal.9.png |
Pressed | _pressed | btn_order_pressed.9.png |
Focused | _focused | btn_order_focused.9.png |
Disabled | _disabled | btn_order_disabled.9.png |
Apps should only define a limited set of dimensions, which are constantly reused.
Dimensions
<WHAT>_<WHERE>_<SIZE> :
- <WHAT> : It can be width(in dp), height (in dp), size (if width == height), margin(in dp), padding(in dp), elevation(in dp). text_size(in sp).
- <WHERE>: It can be any specific item or remove this section if used throughout the application.
- <SIZE>: It can be dp or sp
<!– size for both height and width –>
<dimen name=”size_10dp”> 10dp </dimen>
<dimen name=”size_20dp”> 20dp </dimen>
<!– margin –>
<dimen name=”margin_15dp”> 15dp </dimen>
<dimen name=”margin_20dp”> 20dp </dimen>
<!– padding–>
<dimen name=”padding_2dp”>2dp </dimen>
<dimen name=”padding_3dp”>3dp </dimen>
<!– width–>
<dimen name=”width_20dp”>20dp </dimen>
<dimen name=”width_30dp”>30dp </dimen>
<!– height–>
<dimen name=”height_20dp”>20dp </dimen>
<dimen name=”height_30dp”>30dp </dimen>
<!– text size–>
<dimen name=”text_size_15dp”>15dp </dimen>
<dimen name=”text_size_20dp”>20dp </dimen>
Menu files
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
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.
Values files
Resource files in the values folder should be plural, e.g. strings.xml, styles.xml, colors.xml, dimens.xml, attrs.xml
Project Structure :
- src/main/
- src/androidTest/
- java/
- resources/
- AndroidManifest.xml
- res/
- assets/
- aidl/
- rs/
- jni/
- jniLibs/
Note: src/androidTest/AndroidManifest.xml is not needed as it is created automatically.
Class files
Class names are written in UpperCamelCase.
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.
Resources file names are written in lowercase_underscore.
Java Style Rules
Fields definition and naming
Fields should be defined at the top of the file and they should follow the naming rules listed below.
- Private, non-static field names start with m.
- Private, static field names start with s.
- Other fields start with a lower case letter.
- Static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES.
Example:
public class MyClass {
public static final int SOME_CONSTANT = 42;
public int publicField;
private static MyClass sSingleton;
int mPackagePrivate;
private int mPrivate;
protected int mProtected;
}
Treat acronyms as words
Good | Bad |
XmlHttpRequest | XMLHTTPRequest |
getCustomerId | getCustomerID |
String url | String URL |
Use spaces for indentation
- Use 4 space indents for blocks:
if (x == 1)
{
x++;
}
- Use 8 space indents for line wraps:
Instrument i =
someLongExpression(that, wouldNotFit, on, one, line);
Use standard brace style
Braces go on the same line as the code before them.
class MyClass {
int func() {
if (something) {
// …
} else if (somethingElse) {
// …
} else {
// …
}
}
}
Braces around the statements are required unless the condition and the body fit on one line.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.
if (condition) body();
This is bad:
if (condition)
body(); // bad!
Annotations practices
According to the Android code style guide, the standard practices for some of the predefined annotations in Java are:
- @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.
- @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.
Annotations style
Classes, Methods and Constructors
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 .
/* This is the documentation block about the class */
@AnnotationA
@AnnotationB
public class MyAnnotatedClass { }
Fields
Annotations applying to fields should be listed on the same line, unless the line reaches the maximum line length.
@Nullable @Mock DataManager mDataManager;
Log sparingly
While logging is necessary, it has a negative impact on performance and loses its usefulness if not kept reasonably terse. The logging facilities provide five different levels of logging:
- ERROR: Use when something fatal has happened, that is, something will have user-visible consequences and won’t be recoverable without deleting some data, uninstalling apps, wiping the data partitions, or reflashing the entire device (or worse). This level is always logged. Issues that justify some logging at the ERROR level are good candidates to be reported to a statistics-gathering server.
- WARNING: Use when something serious and unexpected happened, that is, something that will have user-visible consequences but is likely to be recoverable without data loss by performing some explicit action, ranging from waiting or restarting an app all the way to re-downloading a new version of an app or rebooting the device. This level is always logged. Issues that justify logging at the WARNING level might also be considered for reporting to a statistics-gathering server.
- INFORMATIVE: Use to note that something interesting happened, that is, when a situation is detected that is likely to have widespread impact, though isn’t necessarily an error. Such a condition should only be logged by a module that believes that it’s the most authoritative in that domain (to avoid duplicate logging by nonauthoritative components). This level is always logged.
- DEBUG: Use to further note what’s happening on the device that could be relevant to investigate and debug unexpected behaviors. Log only what’s needed to gather enough information about what’s going on with your component. If your debug logs are dominating the log, then you should use verbose logging.
This level is logged even on release builds, and is required to be surrounded by an if (LOCAL_LOG) or if LOCAL_LOGD) block, where LOCAL_LOG[D] is defined in your class or subcomponent, so that there’s a possibility to disable all such logging. Therefore, there must be no active logic in an if (LOCAL_LOG) block. All the string building for the log also needs to be placed inside the if (LOCAL_LOG) block. Don’t refactor the logging call out into a method call if it’s going to cause the string building to take place outside of the if (LOCAL_LOG) block.
There’s some code that still says if (localLOGV). This is considered acceptable as well, although the name is nonstandard. - VERBOSE: Use for everything else. This level is only logged on debug builds and should be surrounded by an if (LOCAL_LOGV) block (or equivalent) so that it can be compiled out by default. Any string building is stripped out of release builds and needs to appear inside the if (LOCAL_LOGV) block.
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:
- Log.v(String tag, String msg) (verbose)
- Log.d(String tag, String msg) (debug)
- Log.i(String tag, String msg) (information)
- Log.w(String tag, String msg) (warning)
- Log.e(String tag, String msg) (error)
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:
public class MyClass {
private static final String TAG = MyClass.class.getSimpleName();
public myMethod() {
Log.e(TAG, “My error message”);
}
}
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.
To only show logs on debug builds:
if (BuildConfig.DEBUG) Log.d(TAG, “The value of x is “ + x);
Class member ordering
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:
- Constants
- Fields
- Constructors
- Override methods and callbacks (public or private)
- Public methods
- Private methods
- Inner classes or interfaces
Example:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private String mTitle;
private TextView mTextViewTitle;
@Override
public void onCreate() { …
}
public void setTitle(String title) {
mTitle = title;
}
private void setUpView() {
}
static class AnInnerClass {
}
}
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:
public class MainActivity extends Activity {
//Order matches Activity lifecycle
@Override
public void onCreate() {}
@Override
public void onResume() {}
@Override
public void onPause() {}
@Override
public void onDestroy() {}
}
Parameter ordering in methods
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.The opposite case are callback interfaces that should always be the last parameter.
Examples:
// Context always goes first
public User loadUser(Context context, int userId);
// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);
String constants, naming, and values
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.
When using one of these components, you must define the keys as a static final fields and they should be prefixed as indicated below.
Element | Field Name Prefix |
SharedPreferences | PREF_ |
Bundle | BUNDLE_ |
Fragment Arguments | ARGUMENT_ |
Intent Extra | EXTRA_ |
Intent Action | ACTION_ |
Example: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.
// Note the value of the field is the same as the name to avoid duplication issues
static final String PREF_EMAIL = “PREF_EMAIL”;
static final String BUNDLE_AGE = “BUNDLE_AGE”;
static final String ARGUMENT_USER_ID = “ARGUMENT_USER_ID”;
// Intent-related items use full package name as value
static final String EXTRA_SURNAME = “com.myapp.extras.EXTRA_SURNAME”;
static final String ACTION_OPEN_USER = “com.myapp.action.ACTION_OPEN_USER”;
Arguments in Fragments and Activities
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.
When an Activity or Fragment expects arguments, it should provide a public static method that facilitates the creation of the relevant Intent or Fragment.
In the case of Activities the method is usually called getStartIntent():
public static Intent getStartIntent(Context context, User user) {
Intent intent = new Intent(context, ThisActivity.class);
intent.putParcelableExtra(EXTRA_USER, user);
return intent;
}
For Fragments it is named newInstance() and handles the creation of the Fragment with the right arguments:
public static UserFragment newInstance(User user) {
UserFragment fragment = new UserFragment();
Bundle args = new Bundle();
args.putParcelable(ARGUMENT_USER, user);
fragment.setArguments(args)
return fragment;
}
Note 1: These methods should go at the top of the class before onCreate().
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.
Xml Rules
Use self closing tags
When an XML element doesn’t have any contents, you must use self closing tags.This is good:
<TextView
android:id=“@+id/text_view_profile”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content” />
This is bad :
<!– Don\’t do this! –>
<TextView
android:id=“@+id/text_view_profile”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content” >
</TextView>
Resources naming
Resource IDs and names are written in lowercase_underscore.
ID naming
IDs should be prefixed with the name of the element in lowercase underscore. For example:
Element | Prefix |
TextView | text_ |
ImageView | image_ |
Button | button_ |
Menu | menu_ |
<ImageViewImage view example:
android:id=“@+id/image_profile”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content” />
Menu example:
<menu>
<item
android:id=“@+id/menu_done”
android:title=“Done” />
</menu>