Last week I wrote Content Provider Iterator, which simplifies the task of dealing with Android’s Content Providers. Reto Meier, the author of what is currently the best Android developer book, got all nervous about my approach. He’s got a point, but so do I.
If you haven’t read Reto’s piece, please hop on over there and do so; I’ll wait till you get back.
To recap; my providerhelper package lets you write the following code:
Reader<Call> calls = new Reader<Call>(Call.class, activity, CallLog.Calls.CONTENT_URI); for (Call call : calls) String number = call.getnumber();
I claim that this is about as idiomatic as you can possibly get, if your idiom is Java’s flavor of object-orientation.
But On the Other Hand ·
Reto, and others, point out that this creates a lot of objects (one per
Call, plus one for any field you choose to store in an Object field) and does
a lot of reflection (one
method.invoke() for each field you want
to extract from the Cursor, for each Call). This, they argue, will have an
unacceptable cost and flies in the face of the official recommendations on
for performance in Android.
Jerome Lacoste actually wrote some code to measure the performance, and it suggested that the slowdown was as much as a factor of ten. So this is not just a theoretical problem. I guess those people who wrote the Design-for-performance guidelines knew what they were talking about.
Well, for some applications, anyhow. The problem is, for others it’s not going to make a damn bit of difference. For example, in my own app code, the delay for reading a few hundred records out of the phone-call log, and doing a bit more work with them than Jerome did, isn’t even measurable. (I’m working to reconcile my result with his; something funny is going on).
At a more general level, I’d like to appeal to Knuth’s Premature optimization is the root of all evil. What Knuth didn’t say, as far as I know, was the reason why his statement is true: nobody is smart enough to predict where the performance bottlenecks will occur in any reasonably complex application. And let’s grant that some “premature” optimization is common practice: as in, the selection of sensible algorithms and data structures.
So, my take-away is: Yes, you have to learn the lessons Reto’s teaching and be nervous about the things he says you should be nervous about.
Having said that, I still believe that the right way to build an application is to do the Simplest Thing That Could Possibly Work, and maybe it’ll be fast enough, and if it’s not, then don’t bloody guess where the problem is, measure it until you know.
Other Gripes · Reto and my commenters also point out that:
Getters and setters are often bad practice, and
the code isn’t thread-safe, and
developers shouldn’t have to inherit from
Those are all fair points, particularly the one about concurrency. I will update the package docs to include warnings about the potential performance problems and all these other gotchas.
What Next? · I’m not sure yet. On the one hand, Reto’s arguments and Jerome’s results are certainly sobering. On the other, I think the problem I was addressing is real: Having read quite a lot of Android apps source, I do think I see quite a bit of tedious ugly code concerned with pulling fields out of cursors; the kind of thing that has me thinking Don’t repeat yourself.
Having said that, I have to observe that the Google-provided apps work pretty well and run pretty fast, and the source code is a lot easier to read than that of a bunch of other open-source projects I could name. So maybe I’m straining at gnats here.
Maybe I’ll end up plastering a big Never do things like
this all over that
providerhelper code. Maybe I’ll find
a way to do away with some boilerplate at a more acceptable cost.
I’m quite positive that I’ll come away a deeper and better understanding of the
Android SDK; this is by way of sharing the lessons.