Automat

František Gažo

Android library for boilerplate destruction

10.

Problem

Boilerplate

new Activity

  • cannot use constructors
  • passing data through Intents
public class NextActivity extends Activity {

    private static final String EXTRA_TEXT = "extra_text";
    private static final String EXTRA_FLAG = "extra_flag";

    public static Intent newIntent(Contaxt context, String text, boolean flag) {
        Intent intent = new Intent(context, NextActivity.class);
        intent.putExtra(EXTRA_TEXT, text);
        intent.putExtra(EXTRA_FLAG, flag);
        return intent;
    }











}
public class NextActivity extends Activity {

    private static final String EXTRA_TEXT = "extra_text";
    private static final String EXTRA_FLAG = "extra_flag";

    public static Intent newIntent(Contaxt context, String text, boolean flag) {
        Intent intent = new Intent(context, NextActivity.class);
        intent.putExtra(EXTRA_TEXT, text);
        intent.putExtra(EXTRA_FLAG, flag);
        return intent;
    }

    private String mText;
    private boolean mFlag;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        Bundle extras = getIntent().getExtras();
        mText = extras.getString(EXTRA_TEXT);
        mFlag = extras.getBoolean(EXTRA_FLAG);
    }
}

new Fragment

  • only default constructor
  • passing data through Bundles
public class SomeFragment extends Fragment {

    private static final String EXTRA_TEXT = "arg_text";
    private static final String EXTRA_FLAG = "arg_flag";

    public static SomeFragment newInstance(String text, boolean flag) {
        SomeFragment frag = new SomeFragment();
        Bundle args = new Bundle();
        args.putString(EXTRA_TEXT, text);
        args.putBoolean(EXTRA_FLAG, flag);
        frag.setArguments(args);
        return frag;
    }










}
public class SomeFragment extends Fragment {

    private static final String EXTRA_TEXT = "arg_text";
    private static final String EXTRA_FLAG = "arg_flag";

    public static SomeFragment newInstance(String text, boolean flag) {
        SomeFragment frag = new SomeFragment();
        Bundle args = new Bundle();
        args.putString(EXTRA_TEXT, text);
        args.putBoolean(EXTRA_FLAG, flag);
        frag.setArguments(args);
        return frag;
    }

    private String mText;
    private boolean mFlag;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        mText = getArguments().getString(EXTRA_TEXT);
        mFlag = getArguments().getBoolean(EXTRA_FLAG);
    }
}

Solution?

APT

  • Java Annotation Processor Tool
  • can generate code
  • cannot modify existing code
  • generated code is debuggable
  • used library:

ByteCode Weaving

  • can modify existing code
  • can generate new code
  • generated code is not visible
  • cannot debug
  • used library:
  • needs additional Gardle task
  • plugin library:

Execution

Annotation Processing

ByteCode Weaving

Result

new Activity

public class NextActivity extends Activity {

    @Extra String mText;
    @Extra boolean mFlag;

}
public class NextActivity extends Activity {

    private static final String EXTRA_TEXT = "extra_text";
    private static final String EXTRA_FLAG = "extra_flag";

    public static Intent newIntent(Contaxt context, String text, boolean flag) {
        Intent intent = new Intent(context, NextActivity.class);
        intent.putExtra(EXTRA_TEXT, text);
        intent.putExtra(EXTRA_FLAG, flag);
        return intent;
    }

    private String mText;
    private boolean mFlag;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        Bundle extras = getIntent().getExtras();
        mText = extras.getString(EXTRA_TEXT);
        mFlag = extras.getBoolean(EXTRA_FLAG);
    }
}

new Activity

  • generates class I
  • 2 methods for each Activity with @Extra:
    • Intent forX(Context c[, T extra, ...])
    • void startX(Context c[, T extra, ...])
I.startNextActivity(context, "some text", true);

Intent intent = I.forNextActivity(context, "some text", true);
// set something to intent
startActivity(intent);
public class SomeFragment extends Fragment {

    private static final String EXTRA_TEXT = "arg_text";
    private static final String EXTRA_FLAG = "arg_flag";

    public static SomeFragment newInstance(String text, boolean flag) {
        SomeFragment frag = new SomeFragment();
        Bundle args = new Bundle();
        args.putString(EXTRA_TEXT, text);
        args.putBoolean(EXTRA_FLAG, flag);
        frag.setArguments(args);
        return frag;
    }

    private String mText;
    private boolean mFlag;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        mText = getArguments().getString(EXTRA_TEXT);
        mFlag = getArguments().getBoolean(EXTRA_FLAG);
    }
}

new Fragment

public class SomeFragment extends Fragment {

    @Arg String mText;
    @Arg boolean mFlag;

}
  • generates class F
  • 1 method for each Fragment with @Arg:
    • Intent newInstance(T extra, ...)
F.newSomeFragment("some text", true);

new Fragment

Use Gradle Plugin

buildscript {
    dependencies {
        // ...

        classpath 'eu.f3rog.automat:plugin:0.2.0'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'automat'

Problems

  • Only few articles about Bytecode Weaving for Android
  • No found examples using both (APT and BW)
  • Gradle Plugin - needed modifications

Future

That's all folks :)

Thanks

Open Source:

Automat

By František Gažo

Automat

  • 537