The use of libraries or frameworks forces us to write a considerable amount of initialization code, often very repetitive and usually difficult to remember; it is what we call boilerplate code. In this talk, different mechanisms available in Android Studio and the Java language will be presented. In particular, we will provide an overview of the code completion mechanisms, ADT Templates, Gradle plugins, Annotation Processors and Android Studio/IntelliJ IDEA plugin system.
2. Tomás Ruiz-López
Software Design Manager at Everyware Technologies
@tomasruizlopez
@everywaretech
/everywaretech
http://www.everywaretech.es
WHO AM I?
Postdoctoral Fellow at Cancer Registry of Norway
Everyware Technologies
tomas@everywaretech.es
5. public
class
MyParcelable
implements
Parcelable
{
private
int
mData;
!
public
int
describeContents()
{
return
0;
}
!
public
void
writeToParcel(Parcel
out,
int
flags)
{
out.writeInt(mData);
}
!
public
static
final
Parcelable.Creator<MyParcelable>
CREATOR
=
new
Parcelable.Creator<MyParcelable>()
{
public
MyParcelable
createFromParcel(Parcel
in)
{
return
new
MyParcelable(in);
}
!
public
MyParcelable[]
newArray(int
size)
{
return
new
MyParcelable[size];
}
};
private
MyParcelable(Parcel
in)
{
mData
=
in.readInt();
}
}
60. <?xml
version="1.0"?>
<recipe>
<dependency
mavenUrl="com.squareup.retrofit:retrofit:1.8.0"/>
!
!
<copy
from="res/values/urls.xml"
to=“${resOut}/values/urls.xml"
/>
!
!
<instantiate
from="src/app_package/Service.java.ftl"
to="${srcOut}/${className}.java"
/>
!
<open
file="${srcOut}/${className}.java"
/>
!
</recipe>
recipe.xml.ftl
PRO TIP: Put an open command at the end of your recipe to make sure
everything executed correctly
63. ADT Templates
Generates multiple files, even projects
Customizable
Only for creation
Automatic UI wizard generated
Complex syntax
Difficult to test and verify correctness
94. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
95. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
PRO TIP: Use com.squareup.JavaPoet
to generate code
96. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
97. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
Allows other processors to
handle the same annotations
98. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
99. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
PRO TIP: Use AutoService
to generate META-INF
100. Processing annotations
@AutoService(Processor.class)
public
class
MyProcessor{
!
@Override
public
Set<String>
getSupportedAnnotationTypes(){
return
Collections.singleton(MyAnnotation.class.getName());
}
!
@Override
public
SourceVersion
getSupportedSourceVersion(){
return
SourceVersion.latestSupported();
}
!
@Override
public
boolean
process(Set<?
extends
TypeElement>
annotations,
RoundEnvironment
roundEnv){
!
Set<?
extends
Element>
elements
=
roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
//
Process
elements
and
generate
code
!
return
false;
}
}
121. About ADT Templates
Official documentation
https://android.googlesource.com/platform/sdk/+/refs/heads/master/templates/docs/index.html
About Gradle Plugins
Writing Custom Plugins
https://gradle.org/docs/current/userguide/custom_plugins.html
!
Lessons learned from our first Gradle plugin for Android,
Victor
https://trello.engineering/victor/
!
Hugo
https://github.com/JakeWharton/hugo
122. About Annotation Processors
Annotation Processing Boilerplate Destruction
https://speakerdeck.com/jakewharton/annotation-processing-boilerplate-destruction-droidcon-nyc-2014
About IntelliJ Plugins
Getting Started with Plugin Development
https://confluence.jetbrains.com/display/IDEADEV/Getting+Started+with+Plugin+Development
!