Skip to content

Code Style

Charleston edited this page Nov 22, 2017 · 7 revisions

Code Style

Java Language Rules

https://source.android.com/source/code-style.html

Code Rule

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:

  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 MainActivity extends Activity {
    
        private String title;
        private TextView txtViewTitle;
    
        public void setTitle(String title) {
            title = title;
        }
    
        @Override
        public void onCreate() {
            ...
        }
    
        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_ |

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.

Example:

    // 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.

Line length limit

Code lines should not exceed 120 characters. If the line is longer than this limit there are usually two options to reduce its length:

  • Extract a local variable or method (preferable).
  • Apply line-wrapping to divide a single line into multiple ones.

There are two exceptions where it is possible to have lines longer than 100:

  • Lines that are not possible to split, e.g. long URLs in comments.
  • package and import statements.

Android Resource Naming

  • BASIC PRINCIPLE

  • All resource names follow a simple convention. <WHERE>_<WHAT>_<DESCRIPTION>

  • Layouts:

  • <WHAT>_<DESCRIPTION>.xml eg. activity_main.xml

    • <WHAT> activity, fragment, view, item ou layout
  • Strings:

    • <WHERE>_<DESCRIPTION> eg. onboarding_title, home_subtitle
      • <WHERE> reduced name of the activity/fragment/view (onboarding)
      • <DESCRIPTION>what it is (subtitle)
  • Ids:

    • <WHERE>_<WHAT>_<DESCRIPTION> eg. edit_financial_btn_confirm
      • <WHERE> reduced name of the activity/fragment/view (edit_financial)
      • <WHAT> btn, txt, lyt, img, edt, etc. (btn)
      • <DESCRIPTION> what this do, or what it is (confirm)
  • Dimensions

  • <WHERE>_<WHAT>_<DESCRIPTION> eg. edit_financial_margin_confirm

  • <WHERE> reduced name of the activity/fragment/view (edit_financial)

  • <WHAT> width, height, size, margin, etc. (margin)

  • <DESCRIPTION> what this do, or what it is (confirm)

Let's first describe every element briefly. After the advantages, we'll see how this applies to each resource type.

<WHAT>

Indicate what the resource actually represents, often a standard Android view class. Limited options per resource type. (e.g. MainActivity -> activity)

<WHERE>

Describe where it logically belongs in the app. (e.g. MainActivity -> main, ArticleDetailFragment -> articledetail)

<DESCRIPTION>

Differentiate multiple elements in one screen. (e.g. title)

LAYOUTS

<WHAT>_<DESCRIPTION>

Layouts are relatively simple, as there usually are only a few layouts per screen. Therefore the rule can be simplified to:

<WHAT> is one of the following:

| Prefix | Usage |
|---|---|---|---|---| | activity | contentview for activity |
| fragment | view for a fragment |
| view | inflated by a custom view |
| item | layout used in list/recycler/gridview |
| layout | layout reused using the include tag |

Examples:

  • activity_main: content view of the MainActivity
  • fragment_articledetail: view for the ArticleDetailFragment
  • view_menu: layout inflated by custom view class MenuView
  • item_article: list item in ArticleRecyclerView
  • layout_actionbar_back_button: layout for an actionbar with a backbutton (too simple to be a customview)

STRINGS

<WHERE>_<DESCRIPTION>

We use <WHERE> to indicate where the string will be used:

Examples:

  • article_detail_title: title of ArticleDetailFragment
  • feedback_explanation: feedback explanation in FeedbackFragment
  • feedback_name_hint: hint of name field in FeedbackFragment
  • all_done: generic "done" string

<WHERE> obviously is the same for all resources in the same view.

IDS

For IDs, <WHAT> is the class name of the xml element it belongs to. Next is the screen the ID is in, followed by an optional description to distinguish similar elements in one screen.

<WHERE>_<WHAT>_<DESCRIPTION> Examples:

  • tab_main -> TabLayout in MainActivity
  • img_menu_profile -> profile image in custom MenuView
  • txt_detail_title -> title TextView in DetailFragment

DIMENSIONS

Apps should only define a limited set of dimensions, which are constantly reused. This makes most dimensions all by default. Therefore you should mostly use:

all_<WHAT>_<DESCRIPTION>

and optionally use the screen specific variant:

<WHERE>_<WHAT>_<DESCRIPTION>

Where <WHAT> is one of the following:

| Prefix | Usage |
|---|---|---|---|---| | width | width in dp | | height | height in dp | size | if width == height|
| margin | margin in dp |
| padding | padding in dp |
| textsize | size of text in sp |

Note that this list only contains the most used <WHAT>s. Other dimensions qualifiers like: rotation, scale,... are usually only used in drawables and as such less reused.

Examples:

  • height_toolbar: height of all toolbars
  • textsize_medium: medium size of all text
  • size_menu_icon: size of icons in menu
  • height_menu_profileimage: height of profile image in menu