Category Archives: Android

BundleButler: Simplifying arguments and savedInstanceState

To make proper use of both Fragment arguments and saved instance state in Android, I found myself frequently writing a great deal of the same boilerplate code. Most of that code looked like this:

public class EditEntryFragment extends Fragment {
    private Entry entry;
    private String title;
    private boolean hasAgreedToTerms = false;
    public static EditEntryFragment createInstance(Entry currentEntry, String title) {
        EditEntryFragment fragment = new EntryEditFragment();
        Bundle args = new Bundle();
        args.putParcelable("entry", currentEntry);
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if(args != null) {
            entry = (Entry)args.getParcelable("entry");
            title = args.getString(title);
        }
        if(savedInstanceState != null) {
            if(savedInstanceState.containsKey("entry") {
                entry = (Entry)savedInstanceState.getParcelable("entry");
            }
            hasAgreedToTerms = savedInstanceState.getBoolean("hasAgreedToTerms", hasAgreedToTerms);
        }
        // use saved entry to populate form fields / load images, etc.
    }
 
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        state.putParcelable("entry", entry);
        state.putBoolean("hasAgreedToTerms", hasAgreedToTerms);
    }
}

Of course bundling all state into a Parcelable or Bundle like this reduces said boilerplate as we’re not keeping track of all form fields or state individually, but we still have to write code to:

  • Check that arguments and state have been provided (null checks)
  • Check that keys we care about exist
  • Decide when to use the saved state of a field over the argument over the default value
  • Bundle each argument in createInstance
  • Store each field into state

Each of these actions is fairly trivial, but leads to a lot of code that is easy to lose track of or get wrong.

Bundle Butler generates this code for you by making a few assumptions.

  1. Arguments and saved state can be treated similarly. They’re both state (arguments are essentially a bootstrapped state).
  2. Arguments and state will be loaded into fields.

This allows us to annotate fields and call a couple of static methods to accomplish the same thing:

public class EditEntryFragment extends Fragment {
    @Argument private Entry entry;
    @Argument("title") private String title;
    @Argument("terms") private boolean hasAgreedToTerms = false;
    public static EditEntryFragment createInstance(Entry currentEntry, String title) {
        EditEntryFragment fragment = new EntryEditFragment();
        this.entry = currentEntry;        
        this.title = title;
        BundleButler.saveArgs(fragment);
        return fragment;
    }
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BundleButler.loadArgsWithState(this, savedInstanceState);
        // use saved entry to populate form fields / load images, etc.
    }
 
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        BundleButler.saveState(this, state);
    }
}

The @Argument annotation causes Bundle Butler to generate adapters used by the BundleButler utility class to build an arguments bundle and manage the entries in the state bundle. The annotation takes an optional key to be used in the bundles. If not provided, it will use the name of the field.

Look for it to be added to maven Central shortly. In the mean time you can build it from source: BundleButler on GitHub. It’s still being developed and contributions are appreciated.

Indispensable Android Libraries

With recent surge in adoption of the new Gradle-based Android build system, it’s easier than ever to incorporate Android library projects (and libraries in general) into your project. Gone are the days of complex pom files, submodules, forked repos, a huge libs folder or worst of all, copying code as-is into your repo (you never did that, right?). Now a full Android library or utility can be included with a one-line addition to your build.gradle file. Here are a few that I find extremely useful in my day to day work. Continue reading Indispensable Android Libraries

Improving RoboGuice Application Start Times

RoboGuice is a fantastic dependency injection framework for Android that wraps Google’s Guice DI library with a set of helper classes and default injections that can make an Android developer’s life much easier. Unfortunately, this comes at a cost. Guice was not designed with mobile devices in mind and instead targets servers where objects startup is long but once you’re up, responses need to be quick. Because of this, startup times for apps using RoboGuice can be noticably long in the best case and uncomfortably long if you’re not careful. Below are some tips and tricks I’ve used to help defer that startup cost and improve the experience for the user. Continue reading Improving RoboGuice Application Start Times

DI on Android Without the Startup Cost: dagger

Anyone who has used a dependency injection (DI) framework on a project can likely speak to its benefits when creating complex systems. Relying on it can help an engineer to design and implement clean, testable software.

Anyone who has tried to write Android applications using a DI framework has likely been disappointed in some degree with current offerings. DI frameworks in Java have largely been written with server architectures in mind and as such are either generally too resource heavy to work on a mobile device. There have been some success stories, but they come with issues of their own. RoboGuice, the Android DI go to, is built around Google’s Guice. Roboguice is easy to set up and very powerful, but it comes with a cost. Because it uses run-time validation of the dependency tree, any application that uses it incurs a startup cost the first time it requests injection. On simple projects with few injected dependencies, this may be less than half a second, but I have seen it go as high as 1.5 on the latest hardware with more complex apps. There are ways to delay this cost or minimize the impact it has on the user experience (another post for another time), but the cost won’t go away.

Enter dagger: Continue reading DI on Android Without the Startup Cost: dagger

Using SimpleExpandableListAdapter

I recently needed to modify one of my apps to change the way I display a list of things with dates from a flat ListView to an ExpandableListView, grouped by day. The items displayed are backed by  a SQLite database which we use ORMLite to interface with. The ListView was already using a custom adapter that extended an ArrayAdapter and supported actions like Delete and Edit on long press. I needed to provide the exact same functionality in an ExpandableListView.
Continue reading Using SimpleExpandableListAdapter

Gson & Deserialization of Objects Containing Arrays

After my practicum team and I banged our collective heads against the wall for several hours trying to force Gson to deserialize json arrays into a collection of complex classes containing their own collections, we chose to go another route entirely. Our problem at the time was that we had blinders on and couldn’t walk away from using Javas Collections library. I came to realize today that Gson does a fantastic job of deseralizing classes with any depth of arrays so long as those json arrays are actually represented as primitive arrays in your java class.

For example: let’s say you had the following json:

[
  {
    "name":"Beagle",
    "colors":["black","white","tan"]
  },
  {
    "name":"Dalmation",
    "colors":["white","black"]
  }
]

Continue reading Gson & Deserialization of Objects Containing Arrays

I Heart roboguice

Since I was introduced to it by @ahsteele, I’ve been in love with the simplicity that roboguice provides for Android development. It introduces the inversion of control principle to your app and much of the Android SDK. With a bit of configuration, you can remove the explicit calls to get resource objects, shared preferences, etc. and instead simply inject them with the use of simple decorators.

For instance, let’s say you needed access to a shared preferences instance. Traditionally, one would need to request a shared preferences object from a context and store it as a member in onCreate or request it every time it’s needed using one of the methods below:

class SomeActivity extends Activity
{
   SharedPreferences prefs = null; // class member
   protected void onCreate (Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      // Method 1:
      prefs = getSharedPreferences("some_key", MODE_PRIVATE);
      // Method 2:
      prefs = PreferenceManager.getDefaultSharedPreferences(this);
   }
}

But with roboguice configured, this class simplifies to:

class SomeActivity extends RoboActivity
{
   @Inject SharedPreferences prefs; // equivalent to method 2 above
   protected void onCreate (Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      // nothing to do here!
   }
}

This can be done outside of an activity class and will use the application context capture the proper SharedPreferences object.

Resources can also be injected, avoiding the need to use findResourceById and cast the resulting object like this:

      // inside method
      Button b = (Button)findViewById(R.id.myButton);

Instead, you can just use the @InjectView decorator:

   // class member
   @InjectView(R.id.myButton) Button b;

You can find some additional examples on the Google Project site. I’ve ended up using roboguice on all of my recent Android projects and haven’t looked back; it makes Android code more succinct and I have discovered that I am a big fan of Inversion of Control in my own code.