Android Code Style And Guidelines

Muhammad Raza Saeed
5 min readDec 29, 2021

--

Before you begin development, you must first pick which architecture you will use throughout the process. Take care of code norms, such as naming conventions, variable declarations, and design patterns, among other things.

Android resource naming:

Always use the snake case naming convention when naming resources, and remember this easy rule:
<what>_<where>_<description>_<size>

What is actually a representation for example (MainActivity is an activity)
Where describes where it logically belongs to. For example (main in MainActivity or userdetail in UserDetailFragment)
Description distinguish multiple elements in a single screen for example (name, age, size)
Size represents size for example (small, medium, large)

Note: Use description and size if required

For Layouts e.g activity_main or activity_splash
For Strings e.g all_done, good_day
For Drawables e.g male_placeholder, female_placeholder
For Ids e.g layout_main, button_proceed
For Dimensions e.g margin_main_button, padding_top

Advantages:

  1. Resources are arranged by screen because Where part identifies the screen from which a resource originates.
  2. Autocomplete will perform better because the project browser or navigator sorts files, resources, and ids alphabetically so that when you search for a given resource or id, the android navigator will better manage the resources.
  3. There will be no more name disputes because in different screens, similar resources are either all or have a different WHERE. All naming collisions are avoided with a fixed naming strategy.
  4. The names of such resources will be cleaner and more sensible in general.

P.S: Despite the fact that this system does not cover all resource types yet, it does provide a simple answer for where the majority of naming difficulty now exists.

Recommended prefixes for resources id’s:

Prefix for Action bar should be ab_
Prefix for Button should be btn_
Prefix for Textview should be tv_
Prefix for Dialog should be dialog_
Prefix for Edittext should be et_
Prefix for Recyclerview should be rv_
Prefix for Menu should be menu_
Prefix for Icon should be ic_

Code guidelines:

  1. Don’t ignore exceptions, for example if you ignore the catch part:

try {
line 1
line 2
line 3
} catch (ArrayOutOfBoundException e) {
// empty catch part
}

Ignoring exceptions like the ones listed above builds landmines in your code that someone else will stumble into one day. Every Exception in your code must be handled in a consistent manner. Depending on the situation, several approaches are taken.

2. Catching generic exceptions isn’t a good idea.

try {
line 1 // may throw ArrayOutOfBoundException
line 2 // may throw IOException
line 3 // may throw ParsingException
} catch (Exception e) { // catch generic exception
handleException();
}

It’s risky since it means that app-level error handling will catch exceptions you didn’t intend (including runtime exceptions like ClassCastException). It hides your code’s failure-handling attributes, so if the code you’re calling adds a new type of exception, the compiler won’t tell you that you need to handle the issue differently. In most circumstances, various sorts of exceptions should not be handled in the same way.

Keep in mind that exceptions are your ally! Don’t worry when the compiler complains that you’re not catching an exception. Smile! The compiler has just made it easier to detect runtime errors in your code.

3. Imports that are fully qualified

This is bad: import SharedUserClass.*
This is good: import SharedUserClass.UserName

4. Definition and naming of fields

Information: You often see that some variables starts with ‘m’ but don’t know the reason. So basically m stands for member and it’s for “non-public, non-static field names.”. This convention is unhelpful to me, but it is a personal opinion.

According to Android Official Documentation:

- Non-public, non-static field names start with m.
- Static field names start with s.
- Other fields start with a lower case letter.
- Public static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES.

For 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;
}

5. Use spaces for indentation

Use 4 space indents for block:
if (x == 1) {
x++;
}
Use 6 space indents for line wraps:
User user = new User(name, email, phone);

6. Use standard brace style

This is bad:

fun getDetail 
{
}

Braces go on the same line as the code before them:

fun getDetail {
}

Or if you are writing single line if statement then:

This is bad:
if (condition)
body();
This is good:
if (condition) body();

7. Same line annotations

Field annotations should all be listed on the same line.
For example:
@Nullable @Mock DataManager dataManager;

8. Limit variable scope

Limit the scope of local variables as much as possible. This improves the readability and maintainability of your code while also lowering the risk of errors. Declare each variable in the block that contains all of the variable’s uses.

For example if you need a new local variable inside try catch so instead of declaring it on the top of your activity or class, you should limit the scope like:User u = new User();
try {
user.getDetails();
} catch(ArrayOutOfBoundException e) {
throw new ArrayOutOfBoundException("index 7, size 7");
}

// Exercise the User
u.getAge();
Or you can also avoid this case by encapsulating this above code block inside a method.

9. Logging guidelines

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)

We utilise the class name as a tag and define it as a static final field at the top of the file as a general rule. Consider the following scenario:

public class MyClass {
private static final String TAG = MyClass.class.getSimpleName();

public myMethod() {
Log.e(TAG, "My error message");
}
}

On release builds, the VERBOSE and DEBUG logs must be disabled. It’s also a good idea to turn off the INFORMATION, WARNING, and ERROR logs, though you might want to keep them on if you think they’ll help you find bugs in release builds. If you decide to keep them turned on, ensure sure they aren’t leaking sensitive information like email addresses or user IDs.

To only see logs on debug builds, follow these steps:

if (BuildConfig.DEBUG) Log.d(TAG, "The value of x is " + x);

10. Class member ordering

Although there’s no single correct solution but utilizing a logical and consistent order will increase code readability and learnability.
It is suggested that you employ the following order:

  1. Constants
  2. Fields
  3. Constructors
  4. Override methods and callbacks (public or private)
  5. Public methods
  6. Private methods
  7. Inner classes or interfaces

Example:

public class MyActivity extends Activity {

private static final String TAG = MyActivity.class.getSimpleName();

private String title;
private TextView tvTitle;

@Override
public void onCreate() {
...
}

public void setTitle(String title) {
this.title = title;
}

private void setUpView() {
...
}

static class AnInnerClass {

}

}

--

--

Muhammad Raza Saeed

Mobile Apps Engineer having 6+ years of experience. I develop both native and hybrid apps. I have extensive expertise in large system architecture development.