GDG-DevFest-2015



GDG-DevFest-2015

0 0


GDG-DevFest-2015

Getting Groovy on Android Presentation for GDG-TC DevFest March 21 2015

On Github pieces029 / GDG-DevFest-2015

Getting Groovy on Android

Andrew Reitz

About Me

Android Developer @SmartThings

@andrewreitz_

github.com/pieces029

Overview

  • Why Groovy
  • Getting it on Android
  • Projects
  • Code Snippets
Assumptions: Know Android, know Java

What is Groovy

A multi-faceted language for the Java platform

Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at multiplying developers’ productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.

Why Groovy

Java

List<StringList<String> names = new ArrayList<String>();
names.add("Mike");
names.add("Dave");
names.add("Steve");

for (String name : names) {
  System.out.println(name);
}

Why Groovy

Groovyfy It!

List<StringList<String> names = new ArrayList<String>()
names.add("Mike")
names.add("Dave")
names.add("Steve")

for (String name : names) {
  println name
}
- Remove ; - Don't need () - println

Why Groovy

More Groovy!

def names = ["Mike", "Dave", "Steve"]

names.each {
  println it
}
- Better list creation - Optional Type def - Each / Awesome Collections API

Why Groovy

Java Model

public final class Person {
  private final String firstName;
  private final String lastName;
  public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  public String getFirstName() { return firstName; }
  public String getLastName() { return lastName; }
  @Override public boolean equals(Object o) { /*lots of code here*/ }
  @Override public int hashCode() { /*lots of code here*/ }
  @Override public String toString() { /*lots of code here*/ }
}

Why Groovy

Groovy Model

@Immutable
final class Person {
  private final String firstName
  private final String lastName
}

def person1 = new Person("Leslie", "Knope")
def person2 = new Person(firstName: "Ben", lastName: "Wyatt") // Named constructors!
Groovy constructors are pretty sweet!

Why Groovy

Java: Android Button Press

button.setOnClickListener(new View.OnClickListener() {
  @Override void onClick(View v) {
    //...
  }
});

Why Groovy

Groovy: Android Button Press

button.onClickListener = {
  //...
}

Why Groovy

Java File Read

int len;
char[] chr = new char[4096];
final StringBuffer buffer = new StringBuffer();
final FileReader reader = new FileReader(new File("/path/to/file"));
try {
  while ((len = reader.read(chr)) > 0) {
      buffer.append(chr, 0, len);
  }
} finally {
  reader.close();
}
System.out.println(buffer.toString());
Have to look it up every time. Commons-IO helps, but not enough Missing try catch around close (auto close in java 7 but not supported in Android)

Why Groovy

Groovy File Read

println new File("/path/to/file").text
Same can be done with Network Calls new URL("http://google.com").text

Why Groovy

Other awesome things

  • DSLs!
  • Extension methods!
  • More Operators!
  • Operator overloading!
  • AST transformations!
Favorte as keyword/operator Evis and Safe Navigation! ?: ?.

Getting it on Android

Standard Android Compilation

Java -> Compiled Java sources -> .class files -> Dex -> classes.dex -> APK File -> Runtime

Getting it on Android

Groovy Android Compilation

Groovy -> Compiled Groovy sources -> .class files -> Dex -> classes.dex -> APK File -> Runtime

Getting it on Android

Problems

  • Bytecode is different
  • No native support for generating classes at runtime
  • Missing java.bean package
  • Multiple Runtimes
  • Not the same behavior as JVM

Getting it on Android

  • Cédric Champeau (melix)
  • Open beans to replace java.bean
  • Groovy 2.4
  • Works with both static and dynamic runtimes!

Getting it on Android

Add the plugin to gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
        classpath 'org.codehaus.groovy:gradle-groovy-android-plugin:0.3.5'
    }
}
1.1.+ support with 0.3.6

Getting it on Android

dependencies {
    compile 'org.codehaus.groovy:groovy:2.4.1:grooid'
}
  • Create folder src/main/groovy
  • Add .groovy files

Projects

SwissKnife

https://github.com/Arasthel/SwissKnife

  • Based off ButterKnife, Android Annotations, and Android AutoParcel
  • AST transformations
  • Awesome Extension Methods

Projects

SwissKnife

class MyActivity extends Activity {
  @SaveInstance public String myString;

  @OnClick(R.id.button) void onButtonClicked(Button button) {
    Toast.makeText(this, "Button clicked", Toast.LENGTH_SHOT).show();
  }

  @OnBackground void doSomeProcessing(URL url) {
    // Contents will be executed on background
  }

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // This must be called for injection of views and callbacks to take place
    SwissKnife.inject(this);

    // This must be called for saved state restoring
    SwissKnife.restoreState(this, savedInstanceState);
  }
}

Projects

Parcelable

public final class Person implements Parcelable {
  private final int id
  private final String firstName
  private final String lastName

  public void writeToParcel(Parcel out, int flags) {
    out.writeInt(id);
    out.writeString(firstName);
    out.writeString(lastName);
  }

  public static final Parcelable.Creator<Person> CREATOR
    = new Parcelable.Creator<Person>() {
    public Person createFromParcel(Parcel in) {
      return new Person(in);
    }

    public Person[] newArray(int size) {
      return new Person[size];
    }
  };

  private Person(Parcel in) {
    id = in.readInt();
    firstName = in.readString();
    lastName = in.readString();
  }

  public getId() { return id; }
  public getFirstName { return firstName; }
  public getLastName { return lastName; }
}

Projects

SwissKnife: Parcelable

@Parcelable
class Person {
  int id
  String firstName
  String lastName
}

Projects

Android Spock

https://github.com/pieces029/android-spock

  • Mocking Support
  • Useful Extensions

Projects

Android Spock

class MainActivitySpec extends Specification {
  @UseActivity(MainActivity)
  def activity

  def "test activity setup"() {
    expect:
    activity != null
    activity instanceof MainActivity
  }

  def "test layout"() {
    given:
    def button = activity.findViewById(R.id.main_button) as Button

    when:
    def buttonText = button.getText()

    then:
    buttonText == "Test"
  }
}

Example

Circle Stacker

https://github.com/pieces029/circle-stacker

Closing

Groovy doesn't fix the problems android has, but it's a great tool to smooth them over.