Here at Level, we're always looking for ways to calm the rough patches of Android and make our jobs more pleasant. The Android operating system is now 6 years old, after all, and its Java target (1.6) is even older than that. Add to that the confusion of the lolcycle and the need to optimize for performance, and you have a lot of opportunities for awkward code.

In the past couple years, the Android community (and Google itself) have invested a lot of work in papering over these pain points. See ButterKnife for view binding, Icepick for state management, Kotlin for code, and the Support Library for literally everything else.

To our knowledge, however, nobody has yet tackled the subtle-but-insidious onActivityResult callback; and if that is your preferred method for DialogFragment results, then things can get hairy pretty fast:

Recipe for Code Spaghetti

  1. Thaw one onActivityResult callback.
  2. Knead in some int resultCode.
  3. Bring a switch statement to a rolling boil.
  4. Stir in lots of unrelated branching code.
  5. Serve (I hope you like it al dente).

Annotations for a Better Tomorrow

Following in the proud tradition of Jake and Frankie, we realized that we could extract all of that ugly flow control into method annotations.

Check it:

public static final int REQUEST_DELETE = 0;
public static final int REQUEST_TEXT_ENTRY = 1;

public void onConfirmDelete() {
    // Burn the world.

public void onTextResult(@Arg("text") String text) {
    // 'text' is automatically extracted from the data Intent.

@OnActivityResult(value=REQUEST_TEXT_ENTRY, resultCode=Activity.RESULT_CANCELED)
public void onTextAborted(Intent data) {
    // Velodrome only fires on RESULT_OK by default. 
    // You can override that behavior in the annotation args. 
    // 'data' is the original data Intent passed to onActivityResult.

@OnActivityResult({100, 101})
public void onOther() {
    // You can even declare a single handler for multiple request codes, if that's your thing.

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    Velodrome.OnActivityResult(this, requestCode, resultCode, data);


dependencies {
    compile 'com.levelmoney.velodrome:velodrome:1.0'

Check out the Velodrome page for a technical rundown of how it works, a discussion on the merits of reflection vs annotation processing and more!

And as always, pull requests are accepted!