How to create a group of File Templates in Android Studio – Part 3

Datetime:2016-08-22 23:21:09          Topic: Android Studio  XML           Share

In the previous two posts, we looked at creating custom live templates andfile templates. I received a question on twitter once I posted the file template tutorial:

@riggaroo Any idea how to create File Templates that create multiple files? Like "Activity" and "fragment" do?

— Justin Angel (@JustinAngel) May 2, 2016

The following slides were shared with me from  Tomás Ruiz-López . I thought I would share my findings thanks to the slides. Android Studio Templates use Freemarker for template definitions. In this post, we will look at creating a set of file templates that can achieve similar results to the default ones in Android Studio.

How to create a group of file templates

In this example, we are going to look at how to create a custom group of file templates for creating MVP functionality. We need to create a Presenter, an Activity and a Contract that defines the interfaces between the two.

  1. Navigate to the location of the templates folder :
  2. {ANDROID_STUDIO_LOCATION}/plugins/android/lib/templates/other/
    
    On MacOS, this folder was the following:
    /Applications/AndroidStudio.app/Contents/plugins/android/lib/templates/other/
    
    Create a folder in the location of your android studio installation with the name of your template – for example MVP Template Activity  .
  3. Define the following files & folder in the folder that you have just created:
    • template . xml   – This will contain information about the template (Name, minSdkVersion, etc)
    • recipe . xml . ftl   – This will contain instructions explaining how to create the template, including what variables to ask the user for and what should be done with those variables.
    • root /   folder – this will contain the template code.
  4. In the template . xml  place the following xml, substituted with your information about your app.
    <templateformat="4"
     revision="1"
     name="MVP Template Activity"
     description="Creates a new MVP classes - Presenter, View and Contract between the two">
     
     <categoryvalue="Other"/>
     
     <parameterid="className"
     name="Functionality Name"
     type="string"
     constraints="class|unique|nonempty"
     default="MvpFunction"
     help="The name of the functionality that requires MVP views"/>
     
     <globalsfile="globals.xml.ftl" />
        <executefile="recipe.xml.ftl" />
     
    </template>
    
    This file contains all the parameters that should be asked for from the user. In this case, I am asking the user for a name for the MVP functionality that we will be creating.
  5. In the recipe . xml . ftl  you define exactly how the recipe should run, what parameters should be requested from the user (the types of parameters too) and the order in which to instantiate them.
    <?xmlversion="1.0"?>
    <recipe>
     
     <instantiatefrom="src/app_package/Contract.java.ftl"
                      to="${escapeXmlAttribute(srcOut)}/${className}Contract.java" />
     <instantiatefrom="src/app_package/MvpViewActivity.java.ftl"
                      to="${escapeXmlAttribute(srcOut)}/${className}Activity.java" />
     <instantiatefrom="src/app_package/Presenter.java.ftl"
                      to="${escapeXmlAttribute(srcOut)}/${className}Presenter.java" />
     
     
     <openfile="${srcOut}/${className}Presenter.java"/>
    </recipe>
    
    We are now specifying the different files that are created, and where to substitute the name of the output file. We also specify which file should be opened at the end.
  6. Then in the root folder, create the following folder structure:
    • root/src/app_package/
      
      In this app_package   folder, you can then create the template files that need to be created when using this template. For my example, I have the following files in the app_package   folder:
      • Contract.java.ftl
      • MvpViewActivity.java.ftl
      • Presenter.java.ftl
package ${packageName};
 
importcom.example.android.presentation.base.MvpPresenter;
importcom.example.presentation.base.MvpView;
 
public interface ${className}Contract{
 
 interface View extends MvpView {
 
 }
 
 interface Presenter extends MvpPresenter<View> {
 
 }
}
package ${packageName};
 
importcom.example.android.presentation.base.*;
public class ${className}Activity extends BaseActivity implements ${className}Contract.View {
 
 ${classname}Contract.Presenterpresenter;
 
 @Override
    protected void onCreate(final BundlesavedInstanceState) {
        super.onCreate(savedInstanceState);
 
        presenter = new ${className}Presenter();
        presenter.attachView(this);
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detachView();
    }
}
package ${packageName};
 
importcom.example.android.presentation.base.*;
 
public class ${className}Presenter extends BasePresenter<${className}Contract.View> implements ${className}Contract.Presenter{
 
}

6. To use it, you might need to restart Android Studio. Once restarted, right click on a package that you want to create the template in and select it from the “New” menu, as below:

You will then be prompted to fill in the variables that you asked for in the template . xml

It will then generate all the classes required for new MVP functionality. I found that I was often creating the same kind of classes and having to look up how to link the presenter and activity to one another. By implementing it as a template, the whole team can use it, which will ensure standardisation and an easy way of creating new screens or classes.

What other use cases can you think of for groups of file templates?

Links:





About List