Making Black-and-White decisions in a Grey world

Alright, so I've been doing a lot of work evaluating what I want to use as a Dependency Injection (DI)/Inversion of Control (IoC) and Android development framework. So far as I see it, there are four main technologies to consider: RoboGuice, Android Annotations, Dagger, and ButterKnife.

And a quick note on what each one is before I get to comparing them. RoboGuice is a full development framework for Android based on Google Guice: it comes with DI, and a whole lot of features to eliminate boring code. Android Annotation is not quite as full-featured as RoboGuice, but as a DI framework is very similar. The biggest difference is in the technique it uses, more on that later. Dagger is a DI container built by the folks at Square, and that's all it does. So far as I can tell, you can actually use it independent of Android. Which means it doesn't have View injection like RoboGuice and Android Annotations. ButterKnife is a view injection toolkit for Android, and basically adds the 'eliminate boring Android code' aspect of the above frameworks. It is not an IoC container, so makes the most sense when you pair it with Dagger. So without further ado, the comparisons!

RoboGuice

Pros:

  • Feature-filled - Seriously. It comes with its own Event Bus (the EventManager) on top of the IoC container, and I'm sure there's even more there.
  • Well-used - RoboGuice lists itself as being used by Groupon, FaceBook Messenger, and other high-profile apps.
  • Reflective - RoboGuice uses reflection to accomplish everything, which means there's absolutely no code generation involved.

Cons:

  • Documentation - The documentation is awful. I'm not saying this to be mean, but the documentation for RoboGuice is simply unusable. Even the JavaDocs are hosted by someone else. If you're already familiar with Guice, you likely will be able to figure out a solution. If not, StackOverflow is about to become a very close friend.
  • Reflective - Can't do any compile-time checking like Dagger, so all bugs are discovered at run-time
  • Feature-filled - RoboGuice has everything, including the kitchen sink, and an extra refrigerator too. It's complicated trying to figure out how exactly something should be done.
  • Inheritance - This is a fairly small point, but you have to inherit from the RoboGuiceActivity and other RoboGuice... classes. Normally this isn't problematic, but can lead to some interesting problems.

Final Thoughts: My biggest complaint about RoboGuice is the documentation. I don't have a lot of history with the framework, and so the barrier to entry is huge. And honestly, that's the only substantive complain I have.

The other minor complaints I have are inheriting from the RoboGuice... objects. Kind of a minor point, and I'm a bit of a perfectionist, but I don't like inheriting from another object to basically just run the injection. I can run it myself. Also, RoboGuice just tries to be everything to everybody, and I think it would do well to pare down everything that's going on. The Android SDK is still a very capable library.

Also, there have been comments on the internet about the penalty of using reflection vs. compile-time injection, and honestly, I haven't seen anything to actually substantiate these claims. Technically, yes, it is an extra cost to do the reflection. From everything I can see though, the cost is negligible.

So I don't plan on using this, but if you need a one-stop-shop solution, RoboGuice is the way to go. It's battle-tested, and is the most feature-filled of anything here.

Android Annotations (AA)

Pros:

  • Code generation - AA works by generating the code you need at compile time, rather than doing anything at run-time. This means there's no overhead for using the reflection APIs.
  • Feature-filled - Because AA runs at compile time, it can do some fancier things. For example, annotation a method with @Background allows you to run an arbitrary method off the main thread without using AsyncTasks
  • Documentation - I hate that I need to actually include this as a Pro, I feel like it should be a given. That being said, the documentation for AA is pretty great. The community seems to be fairly active too, so that's great.
  • RoboGuice compatibility - AA went above and beyond to make sure their framework plays nice with RoboGuice, so you can have something of the best of both worlds

Cons:

  • Code generation - Part of what allows AA to do some amazing stuff makes it harder to understand. I don't fault the designers for this, it was going to be inherent in doing code generation to start. That being said, the semantics of using MyClass vs. MyClass_, and when the injection of @Beans and @ViewByIds are complete can be confusing.
  • JSR-330 - All the other injection frameworks (Dagger, RoboGuice) are JSR-330 compliant, Android Annotations is not. Not that big of a deal, but is helpful if other people are working with your project, and I think the names are better in the JSR. Also means that AA is missing the Producer<T> pattern that both Dagger and RoboGuice supply.
  • Opinionated - Because AA uses generated classes, you have to use their supplied patterns. For example, the setArguments() method goes away in Fragments, you have to use MyFragment_.builder().myArgument().build(). To be fair, it makes type checking far simpler, but you do have to go through the builder.

Final Thoughts: Android Annotations was my original pick when starting to code MinimalBible. It has all the functionality of RoboGuice that I would actually use, the @Background annotation is awesome, and the documentation was incredibly helpful.

That being said, my largest complain is one of the biggest reasons I was attracted to AA in the first place - code generation. I realize there is no other way this could have been done. I certainly don't fault the developer for this, but trying to understand when to use the Class_ notation I can see getting out of hand quickly. Plus, you need to understand the semantics of AA on top of DI.

So all said, I think I'd prefer Android Annotations over RoboGuice. But only slightly.

Dagger / ButterKnife

Note: I realize these are separate products, but they work so well together, and you need both to actually rival RoboGuice or AA

Pros:

  • Code Generation - Here's another code generation framework, so no reflection penalty. Also, Dagger is great about notifying you of errors in your injection code, so you don't have to wait until runtime to find the bugs (like RoboGuice). You also don't have to worry about Class_ semantics (like AA).
  • Focus - These are very focused libraries. They're worried about doing a few things, and doing them well. You won't have confusing APIs to navigate through.
  • Shiny - The libraries are shiny and new. This isn't a giant selling point, but these libraries are very up-to-date and modern with current techniques, design patterns, etc. They're Good Code.
  • Explicit - Dagger forces you to be explicit about your design, which is good style, and you don't have to understand the semantics underlying a framework like AA.

Cons:

  • Limited API - While Dagger and ButterKnife are very clear about what they do, it also means they don't have functionality other frameworks do. Just means you're left to do some of the code yourself.

Final Thoughts: While I didn't put much down for the cons, I do want to stress the point - the limited API can be a big deal. Using Dagger/ButterKnife will definitely save time, and make your code more readable, but there are still significant chunks of functionality you're left to do yourself. That may be more your style (like me), but in fairness, Dagger and ButterKnife are relatively limited. Relative in the sense that RoboGuice and AA provide a huge amount of functionality. You will have to write more code by hand.

At this point, I'm planning on using Dagger/ButterKnife for the backbone of my app. The fact that I don't have a confusing and complex API to navigate is awesome, and I think there's something to be said for having a library that is very focused on what it actually wants to get done.

Side note, I'm planning on using Auto Factories as well for some of the more complicated producers I have in mind. Right now the only formal "release" is a 0.1-beta, but I think it's ready for some usage.

Bonus Round: Android Annotations + Dagger

Note: You can actually use Dagger as the IoC container and rely on AA for the Android meta-programming. I looked into trying to use this as well, and hope that it's helpful, as there is very little information about programming this way on the internet.

Pros:

  • Two libraries - Get the functionality of a JSR-330-compliant IoC container, and a full-featured Android toolkit! The power of Android Annotations, and the usability of Dagger!

Cons:

  • Two libraries - It is still a bit confusing trying to mix two libraries. For example, both AA and Dagger provide a @Singleton annotation, so you need to make sure you understand which one you're using.
  • Code Generation - You still have to understand some of the semantics of using AA. For example, you can't @Inject MyClass, but have to:
@Provides<MyClass>
public MyClass provideClass() {
    return (MyClass)new MyClass_();
}

If you tried to actually inject the original class, it wouldn't have the functionality actually supplied by AA. And when you're trying to do this with @Singleton as well, things can get confusing.

Final Thoughts: You can find a full-featured project demonstrating Dagger and AA over here. It's a great little project that demonstrates some of the complexity of mixing DI frameworks.

Overall, I will have no reservations about using Android Annotations in the future if I think the readability cost of generated MyClass_s is surpassed by what AA can offer. For now though, I'm not convinced I need Android Annotations.

In the end

For me personally, I plan on using Dagger and ButterKnife to make up the largest part, if not all of, the app. I think they provide the best feature count while not being too opinionated about how I'm supposed to program.

I'm not at all averse to integrating Android Annotations later on down the line should they provide functionality I need. I think it's a great project, and using code generation I think is pretty cool. However, the functionality gain would have to outweigh the cost of needing to understand the semantics of AA.

RoboGuice is the framework I wish I could use, but would take far too much of an investment to pick up. Again, the documentation is awful. From what I've read on their Github page, you need to extend from RoboGuice... whatever. From some instructions on upgrading from 1.1 to 2.0, it appears that you no longer need some of the extends. However, that documentation comes from the Google Code page, which is outdated (development happens in Github). To be fair, there is documentation about the upgrade available on Github as well, but it's not nearly as detailed. Plus, they're developing 3.0-alpha 2 at the time of writing. I just really don't know where to begin.

I hope this helps you think through which container/framework is right for you. I'm happy to answer any questions you have, just send an email!

P.S. While writing this post I discovered that someone else wrote something similar: http://vardhan-justlikethat.blogspot.com/2014/03/android-dependency-injection-roboguice.html However, it didn't seem to actually discuss the technologies in-depth enough, and the author didn't seem to actually understand what the technologies did. I think this article provides a bit more help actually evaluating each piece of software.

(insert joke about thinking outside the box here)

So, I've been trying to refactor some of the code design recently. Most of this is centered around the DownloadManager class, but the BookListFragment is involved as well. Before we get too much farther though, let's explain the use case.

The BookListFragment is responsible for displaying a ListView of books available for download, whether Bibles, Dictionaries, Commentaries, etc. There is one fragment per category of books. However, trying to refresh the list of available books is a very expensive operation. So, there is a DownloadManager to make downloading easy, and provide a caching mechanism. This class should be a Singleton to ensure that we re-use the list of books.

And that's the basic use case. Time for some code.

BookListAdapter.java

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    BookItemView itemView;
    if (convertView == null) {
        itemView = BookItemView_.build(this.ctx);
    } else {
        itemView = (BookItemView) convertView;
    }
    itemView.bind(getItem(position));
    return itemView;
}

BookItemView.java

@EViewGroup(R.layout.list_download_items)
public class BookItemView extends RelativeLayout {
    @ViewById (R.id.img_download_icon) ImageView downloadIcon;
    @ViewById(R.id.txt_download_item_name) TextView itemName;
    @ViewById(R.id.img_download_index_downloaded) ImageView isIndexedDownloaded;
    @ViewById(R.id.img_download_item_downloaded) ImageView isDownloaded;
    public BookItemView (Context ctx) { super(ctx); }
    public void bind(Book b) {
        itemName.setText(b.getName());
    }
}

Here's what's going on: The BookItemView is responsible for displaying an individual element in the list. AndroidAnnotations is responsible for injecting the LayoutInflater, and individual views (the @ViewById). From there, the BookListAdapter can then build individual elements of the list using BookItemView_.build().

This works mostly fine, but here's my issue - the BookItemView is small enough, I feel it should be an inner class. I can't do that with AndroidAnnotations. Also, the astute reader will notice that I'm building a BookView_, not a BookView. That's AndroidAnnotations generating the class for me. Which is exactly what it should be doing, but in my limited experience I've been having to learn the semantics of when/not to use the generated class. Plus when you have a lot of generated classes all over the place, I think it will get complicated.

Onward to the DownloadManager. I haven't committed code for this yet, but I'm hoping to illustrate my point. The class needs to be a singleton, and will eventually need an EventBus inject. I imagine it would look something like this:

DownloadManager.java

@Singleton
public class DownloadManager {
    @Inject EventBus downloadBus;
    // Extra methods to actually do stuff here
}

Now, the first question is, where do I get @Inject from? I'm wanting to use Dagger, as it doesn't force me to use Class_ naming, and is JSR-330 compliant (which mostly means I think the @Bean naming used by AndroidAnnotations looks weird).

The second question is: where does @Singleton come from? That's a little bit ambiguous. Both Dagger and AndroidAnnotations provide an annotation, but one forces me to use the Class_ naming (AndroidAnnotations), one doesn't. One forces me to build an ObjectGraph at runtime (Dagger), one doesn't. This can get very confusing.

Realizing I was about to run into this confusion, I ported the existing AndroidAnnotations code to use ButterKnife. ButterKnife is a library used to support view injection (but does a bit more). It's not as feature-filled as AndroidAnnotations, but doesn't require that I use Class_.

You can check out the code over here. The interesting bits that use ButterKnife are here. ButterKnife requires me to write a bit more boilerplate code, but doesn't force the class naming rules on me. It's a bit of a tradeoff.

So that's a quick overview of the problem. All that to say, I'm questioning what I should use as a framework. I like the functionality AA provides, but it comes with a readability/understandability penalty. Coming from Python, I'm a big fan of making things explicit, but AA does provide a lot. ButterKnife/Dagger are both incredibly well-designed, and very focused. Which means they leave me to do some of the legwork myself.

I've also been investigating RoboGuice as well, and I'm going to write another blog post comparing everything soon!

But I'm still not a fan of Gradle

So, I've wanted to switch to Android Studio for a while. Eclipse as an IDE is a great tool, but largely, it seems to be showing its age. I've just not had great experience with it before, and trying to configure plugins, etc. Plus, Android Studio offered a lot of new features that looked cool.

Problem: Configuring builds to use Gradle.

JSword is going to be used for most of the backend functionality, MinimalBible is the user interface driving everything. The JSword library is built using Ant, and I have another Ant build responsible for tweaking the original library (currently it just shades dependencies and builds an uberjar).

So my build of JSword was going just fine, but I wanted to have a one-click build of the entire MinimalBible app (and eventually use something like Travis). That means getting a build of JSword working alongside the main build.

Originally, it would have made the most sense to stick with Ant builds and re-use targets from that. But me being adventurous and wanting to try the new shiny tooling, I gave Gradle a shot. The results really didn't pan out.

To be honest, I don't really remember why I gave Android Studio a second shot. But I did, and got a preliminary build working after an hour or two. I knew the build wasn't perfect, but developing in Android Studio was now a live option.

The next step was trying to get a build working on Windows. That wasn't incredibly challenging, but Windows was complaining about a builtBy clause in the dependencies. I'm not sure why Linux didn't complain the same way, but oh well. So at this point, the build is working on Windows as well.

The final problem was the bootstrap build. All the builds prior succeeded because the jsword.jar file already existed in the libs/ folder of the project. When you deleted the JAR and tried to build it would fail. But if you tried to rebuild, the JAR already existed as part of the last build, and so the current build would succeed. This, however, would lead to a build failure on any sane CI system, plus it's ugly.

So, I did what any sane developer would do after failing to understand the Gradle build system, and posted a StackOverflow question. As of the time of writing, there were no answers, but I did get it figured out on my own.

What follows next is not an explanation of why the code works, but more so a "here's what I did and it fixed my problem." There were two big changes to make:

Main app:

The way the build originally worked was that a task ran a stubbed Gradle build file, and this build file imported the Ant targets from my build of JSword (the idea I used is over here). This is problematic since Gradle is then unable to track what is generated from this (and I assume this is the reason why the new JAR wasn't added as a dependency).

The new way of doing things is to run that build as part of a different Gradle project, and export the artifacts of that project. So basically instead of the main app being responsible for building the external artifact, the main app just depends on what my JSword build produces. You can find the exact changes over here

JSword build:

My build of JSword is now responsible for exporting the artifact from Gradle. However, I still want to depend on Ant targets, since that's what the underlying library actually uses. In the future, I might switch to pure Gradle, but for now, it's working. So, I added an artifacts section, made a specific configuration, and then the artifact now depends on the task which actually generates the JAR file for JSword.

So the first iteration of the build was complete, and I could now build the entire MinimalBible app using Gradle, without including the jsword.jar in the app itself. Daringly so, I set up my git tree in another location to guarantee everything was working correctly. Turns out I forgot to add the artifact dependency on the build task. I fixed that here.

Wrapping up

But now the entire build works correctly, and I can use Gradle! All told, it took me a lot longer than I'd like to get everything set up. With great power comes great responsibility, and honestly, the Gradle documentation was of very little help in trying to get my build set up. I did eventually get a solution (and a good solution at that), and I'm glad I put the time in to make the switch - it seems everyone is migrating to Android Studio, and trying to do this in the future after having set up an Ant build for MinimalBible would have been a nightmare. Starting with Gradle I think will make things easier.

So Android Studio is now working. I have a good, clean, build of MinimalBible going that I should be able to evolve as my needs change. I still really don't like Gradle, but I can understand that when you're working with an Ant build with ~1500 lines you need a build system as complex as Gradle. At this point, we'll call it good.

Singletons, AsyncTasks, & EventBus! Oh my!

So, MinimalBible is my first full-scale Android app. I'm trying to do what I can to make sure the code is readable and follows good design patterns. To that end, let me describe the problem:

I need to fetch the list of modules available for download (may or may not be from the internet, not worried about that here). To do so is a relatively expensive operation (since it may involve the internet) so using the Fragment that displays the module list is right out. Some potential solutions:

  • Eat the cost of fetching the list, each Fragment fires an AsyncTask
  • The Fragment is initialized with the list it needs
  • Have some external singleton class cache the list in memory, and each fragment can retrieve it from that class
  • Have a service responsible for doing the download, everyone comes to the service
  • If no value exists, Fragment displays that there is no information, and manually force a reload when the information has been retrieved

This is complicated by the fact that the Fragment should be able to retrieve the list synchronously if it has already been loaded. That is, the Fragment needs to know if the value exists and it can do its work, or if it needs to wait a bit. Since the Fragment is on the UI thread, I can't assume a synchronous operation unless the value is already prepared.
So the basic problem is: I need to get a value asynchronously, but how do I cache it to re-use? Or, who is responsible for caching? None of the solutions above seem to have a sound answer to the problem. The solution I chose then doesn't fundamentally solve the problem either. But I'm more than happy to accept suggestions on how to do this differently!

First off, somebody has to be responsible for doing the work of actually fetching the modules, whether from the internet, or from the jSword cache. Because fetching from cache is still an expensive operation (2-3 sec.), it's easier to have one AsyncTask responsible for doing all of that work.

Second, I only ever want this AsyncTask to run once. The module list (hopefully) can stay persisted in memory to be re-used by the different Fragments that need it. That means that there needs to be a Singleton somewhere along the line that's responsible for caching the value.

Finally, that Singleton has a method available to inspect whether the content the AsyncTask was fetching exists yet.

That's the basic methodology I used. However, instead of caching the returned value in the parent Singleton, I used the EventBus to handle it for me. This way, I avoid the boilerplate of an Interface/Listener pattern, and I avoid the Sleeping Barber problem.

The EventBus is an asynchronous communication bus that allows us to connect senders and receivers of POJO objects. This way, the Singleton I was describing above retains a reference to the bus the AsyncTask will post on, and connects listeners to it. After that, the EventBus has a concept of sticky events, which are events persisted in memory until explicitly cleared. So, let's get into some actual pseudo-code!

FetchTask.java

class FetchTask extends AsyncTask<...> {
    private EventBus downloadBus;
    public FetchTask(EventBus downloadBus) {
        this.downloadBus = downloadBus;
    }
   
    public doInBackground(...) {
        // Do the deed
        downloadBus.postSticky(results);
        return results;
    }
}

DownloadManager.java

class DownloadManager {
    private EventBus downloadBus;
    private DownloadManager instance;
 
    private DownloadManager() {}
    public static DownloadManager getInstance() {
        if (instance == null) {
            instance = new DownloadManager();
            instance.downloadBus = new EventBus();
            new FetchTask().execute();
        }
    }
    public EventBus getDownloadBus() {
        return this.downloadBus;
    }
}

Fragment.java

class Fragment {
    public void init() {
        EventBus downloadBus = DownloadManager.getInstance().getDownloadBus();
        Results results = downloadBus.getStickyEvent(Results.class);
        if (results == null) {
            // The operation hasn't finished yet, so notify us when done
            downloadBus.registerSticky(this);
        } else {
            // Operation is already done, initialize now
            initUI(results);
        }
    }
   
    public void onEventMainThread(Results results) {
        // EventBus will call this
        initUI(results);
    }
   
    public void initUI(Results results) {
        // Initialize the UI - can safely assume we're on main thread
    }
}

So, let's quickly review what's going on - the Fragment gets initialized, and gets the Download manager, so it can get the event bus. Then, since the AsyncTask is started alongside the new DownloadManager, we register that we should be notified when done.

Then the DownloadManager starts the initial AsyncTask to download the list, and cache it in the EventBus. Finally, we postSticky() and call it a day.

After this, any new Fragments checking the downloadBus will see that the value already exists, and can do work.

So this isn't a perfect implementation, and honestly, just shoves the problem onto the EventBus. That being said, it's a sane implementation, and is relatively readable.

TODO: Switch around some of the singletons to use dependency injection. I've got my eye on Dagger.

But Gradle is worse

So, one of the first goals in building MinimalBible was getting the underlying library building correctly. I’m using jSword to drive most of the underlying functionality of the app – downloading Bibles, searching Bibles, displaying the text, etc. I have incredibly little experience with Java build systems, but in my experience prior, I had worked with Maven a bit. So when I noticed a pom.xml file, I thought I had it made. Turns out the pom.xml was outdated, and for an old build of the library.

Looking at And-bible was one of the things that first clued me in that I was approaching this the wrong way (the fact that the build was producing a jsword-1.6.jar when I knew the build was at least at version 2.1 was the other). The build.xml file also looked important, so I decided to do some more research. Here’s what I’ve learned.

There are a lot of different systems to build Java projects (I come from Python/C). The three most prevalent are Gradle, Ant, and Maven. By default, Android projects (using Android Development Tools in Eclipse) use none of these. Small-scale Android apps that don’t rely on a lot of extra libraries or other projects simply don’t need the level of functionality provided by any of these. But for the apps that do need extra functionality, you’re going to need to put a build system in place.

I’ll start with Maven, since it seems to be the least used in the Android world. There’s a tutorial and a plugin for doing it, but on the whole I didn’t see a whole lot of information on how to use it. That being said, the Maven project retains a central repository of Java libraries that all the other build systems rely on. This way, you can declare dependencies on other libraries, and have the build system automatically download and install them. Lovely.

Ant seems to be the most well-used (if soon to be phased-out) build system in use with Android. ADT has support for generating an Ant build file, and Google has info on how to use Ant with ADT online. However, Ant in and of itself does not have the dependency management that Maven and Gradle do. For that, we rely on a different library known as Ivy. This way, while Ant handles the build process, Ant can invoke Ivy to fetch all the needed libraries before actually compiling. This build system is what is in use by jSword, and they have a fairly nice build set up.

Gradle is the final build toolkit I’ll talk about. First things first, Gradle is powerful. Their manifesto even says so: “Make the impossible possible, make the possible easy and make the easy elegant.” Gradle is also the build system used by Android Studio, the IDE that will eventually replace ADT. So starting as a new project, I thought it would be a good idea to give Android Studio/Gradle a spin. This is eventually going to be the way of the future.

Getting the initial Eclipse project imported wasn’t too complicated, the documentation for doing that is pretty simple. I generated my build.gradle file, and imported the project. And that’s about as far as I got.

The first order of business was making sure that I could build the jSword project using the new Gradle system. Building the Android project itself I’m sure is incredibly simple, I can get to that later. I wanted to first make sure it would be possible to even get the underlying library working first. To that end, I started doing some research and playing around with getting Ant to work with Gradle. Theoretically, Ant build tasks are first-class citizens in Gradle world. The problem is, Gradle has no way of namespacing the imported Ant tasks. That means if there’s a naming conflict, the build fails (there’s a patch to fix this coming up). While this isn’t an issue if you’re just migrating from Ant to Gradle, if you’re trying to use both Gradle and Ant at the same time, this will cause catastrophic problems. Since I don’t intend to fork jSword for Gradle alone, I needed to come up with something different.

For a while I tried to hack together namespacing by putting the jSword Ant tasks into another project. You can find an example (that I assume worked for the author) over here. This didn’t really work for me. By this time, I had been checking the And-bible build script trying to see how its author solved this problem. Without having any actual knowledge of how to write Ant tasks, what I learned by just looking at the code was that he copied over the original source, merged in his modified code, and then compiled the entire thing. And to be honest, I didn’t even try to attempt this with Gradle. While I’m sure Gradle is more than capable of doing this, it wasn’t worth the effort to figure it out; I had a build I could imitate and use as a starting point.

And so, using the And-bible build.xml as a starting point, I wrote my own build script, which is now available over here. I’ll have more information about actually writing the build script in another post!