Upcoming and OnDemand Webinars View full list

Android Studio Live Templates

Bolot Kerimbaev

Code completion can improve your productivity by reducing how much you have to type, but there are situations when a more powerful tool is needed. Thanks to Android Studio and IntelliJ, live templates make it much easier to focus on just the things you care about.

Live Templates

Live Templates are code snippets that I can insert into my code by typing their abbreviation and pressing tab. They live in the Editor section of the Preferences.

Live Templates in Preferences

A template contains hard-coded text and placeholder tokens (or variables). The parts that are marked by the $ character on either end are variables and normally would be the things that I’d be expected to type in.

For example, one of the built-in templates looks like this:

for(int $INDEX$ = 0; $INDEX$ < $LIMIT$; $INDEX$++) {
  $END$
}

Here, we have three variables $INDEX$, $LIMIT$ and $END$.

  • $END$ is a special predefined variable that controls where your cursor will be placed once you’re done filling out the template. We will have to fill out the values of the other two.
  • To use this template, I will type fori in the Java file and press tab. Android Studio will expand the template and put the cursor on the first variable that needs to be replaced. In this case, it will put the cursor where the template has the $INDEX$ token.
  • As I type something, the other two places where $INDEX$ appears will copy what I’m typing, live!
  • When I’m done naming the index variable, I will press tab or return and the cursor will move to the next variable that needs to be defined, which is $LIMIT$.
  • Finally, after I finish typing in the $LIMIT$ variable, pressing tab or return will place the cursor where the $END$ variable is and will stop the template fill-out session.

Templates in Action

Let’s look at a more complex example.
In our Android Programming Guide, we use the newIntent pattern for Activities and the newInstance pattern for Fragments. Typically, creating a new Activity/Fragment pair involves the following steps:

  • Create the newIntent method in the activity.
  • Create the constant(s) for the names of extras to be passed with the Intent.
  • Create the getFragment method that reads the Intent extras and passes them on to the fragment’s newInstance method.
  • Create the newInstance method in the fragment.
  • Create the constant(s) for the names of the arguments to be set on the fragment.
  • Create the instance variable(s) to store the values of the arguments.
  • Read the arguments in the onCreate method.

In this video, I demonstrate how live templates make it much easier to focus on just the things I care about, rather than the boilerplate.

In the first part of the video, I’m using my “Activity New Intent with Arguments” template. I type ania, the abbreviation I assigned to it, then hit <tab> so Android Studio expands the template, and then I type these characters: String<tab><tab>scannerId<tab>. I end up with this code:

public class ScannerActivity extends SingleFragmentActivity {
    private static final String SCANNER_ID = "ScannerActivity.SCANNER_ID";

    public static Intent newIntent(Context context, String scannerId) {
        Intent intent = new Intent(context, ScannerActivity.class);
        intent.putExtra(SCANNER_ID, scannerId);
        return intent;
    }

    @Override
    protected Fragment getFragment() {
        String scannerId = getIntent().getStringExtra(SCANNER_ID);
        return ScannerFragment.newInstance(scannerId);
    }
}

I have another template, “Fragment New Instance with Arguments.” I type the abbreviation I assigned to the template, fnia, then <tab>, and get the expanded template. Then I type the same sequence of characters as for the ania template: String<tab><tab>scannerId<tab>. This is the result:

public class ScannerFragment extends Fragment {
    private static final String SCANNER_ID = "ScannerFragment.SCANNER_ID";

    private String mScannerId;

    public static ScannerFragment newInstance(String scannerId) {
        ScannerFragment fragment = new ScannerFragment();
        Bundle args = new Bundle();
        args.putString(SCANNER_ID, scannerId);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mScannerId = getArguments().getString(SCANNER_ID);
    }
}

Not too bad for just under 30 keystrokes.

Creating Templates

There are two parts to live templates. One is the template itself and the other is the definition of the variables. This is my ania live template:

private static final String $EXTRA_PARAM$ = "$CLASS_NAME$.$EXTRA_PARAM$";

public static Intent newIntent(Context context, $EXTRA_CLASS$ $EXTRA_VAR$) {
    Intent intent = new Intent(context, $CLASS_NAME$.class);
    intent.putExtra($EXTRA_PARAM$, $EXTRA_VAR$);$END$
    return intent;
}

@Override
protected Fragment getFragment() {
    $EXTRA_CLASS$ $EXTRA_VAR$ = getIntent().get$EXTRA_CLASS$Extra($EXTRA_PARAM$);
    return $FRAGMENT_CLASS$.newInstance($EXTRA_VAR$);
}

Note that variables are deliniated by the $ symbol. Normally, each variable is what you need to type in. If a variable appears in multiple places, all of them are updated simultaneously as you type. It’s possible to customize these variables and even to automatically set their values based on other variables.

For example, $CLASS_NAME$ is defined as expression className, which evaluates to the name of the current class. Here’s the full list of definitions:

Name Expression Default Value Skip if Defined
EXTRA_CLASS typeOfVariable(VAR)   [ ]
EXTRA_VAR suggestVariableName   [ ]
CLASS_NAME className   [x]
EXTRA_PARAM capitalizeAndUnderscore(EXTRA_VAR)   [x]
FRAGMENT_CLASS groovyScript("_1.replaceAll('Activity','Fragment')", CLASS_NAME)   [x]

Three of the variables are marked “Skip if defined,” so I don’t need to type them; their names are derived from what I have already typed. I can even use groovyScript to evaluate expressions beyond the fairly rich predefined set.

As I noted earlier, $END$ controls where your cursor will be once you’re done filling out the template. In this example, I want to put it inside the newIntent method just before the return statement, so that I can customize the Intent object further. For example, I could add flags or more extras.

The fnia template is very similar:

private static final String $ARG_PARAM$ = "$CLASS_NAME$.$ARG_PARAM$";

private $ARG_CLASS_DITTO$ m$INST_VAR$;

public static $CLASS_NAME$ newInstance($ARG_CLASS$ $ARG_VAR$) {
    $CLASS_NAME$ fragment = new $CLASS_NAME$();
    Bundle args = new Bundle();
    args.put$ARG_CLASS$($ARG_PARAM$, $ARG_VAR$);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    m$INST_VAR$ = getArguments().get$ARG_CLASS$($ARG_PARAM$);
}

I had to use a little trick in this template. I created a special variable, $ARG_CLASS_DITTO$. that’s a copy of the $ARG_CLASS$ variable. The reason I duplicated them is to force the cursor to start at the type of the parameter of the newInstance method. If I didn’t do this, the cursor would first jump to the type of the instance variable, then to the name of the parameter.

Thanks to live templates, I’ve reduced the amount of typing I have to do when creating new Activities and Fragments. Of course, there are many other situations where Live Templates would come in handy as well. I’m sure lots of you have your own productivity tips and examples of Live Templates, so please feel free to share with your fellow developers in the comments!

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project