As I've recently announced on my blog, I've started the porting of my current mobile project to Android. Since the current version of the project is made in JavaFX, it's more a redesign from scratch, rather than a port - but at least I know the user scenarios and I can formulate some preliminary points about comparing the two technologies. Bear in mind that this post is not a comprehensive one: as the title says, it's the first feedback from a newbie (for the record, I'm writing it after
several a few weeks of "background study" - articles read in chunks of free time - and two days of programming; the code I've written so far is available at https://kenai.com/hg/bluebill-mobile~android-src, tag dzone20100420).
Points below are mostly in random order.
- Pervasivity (+?). I did schedule the intention of learning Android a few months ago, with no specific deadline. Then, I accelerate things as, at the moment, there are no new announcements about JavaFX mobile, I mean, the platform is great but runs only on a handful of Windows Mobile headsets. This doesn't mean that Oracle is not working on new endorsement by manufacturers and I still have hopes - but it's a matter of fact I need people to try out my stuff and it's extremely difficult to do if it only runs on JavaFX. I hope to have more luck with Android.
- Productivity (++). As Osvaldo Pinali recently said on the JavaPosse mailing list, from the programmer's point of view Android is Java: you don't learn a new language and you're confident with a good subset of the Java runtime. I was able to reuse some code I already had (simple for now, I'm going baby steps), but I know I'll scream out loud when I'll need BufferedImage. The missing Swing is a different story (see below).
- Software factory (+). Maven works pretty well (thanks to the maven-android-plugin) and since I've spent so many months to set up my standard software factory with Maven and Hudson, I don't want to depart from it, if possible. I've been able to use it, unchanged, for my Android project - this means that I've got immediately Cobertura coverage, Findbugs and other metrics and Hudson integration (to be honest, I've still to fully verify it: at the moment, you see red balls because I've not yet installed the Android runtime on my Hudson host - see below).
- Runtime availability (-). The Android runtime is of course available for free, but it requires a graphical UI to install the real stuff (since it's downloaded from an update center). This is a PITA for my Hudson host, where I don't have a graphical console. I'll have to install it on a local Linux box and then upload a tarball. Since I'm a lazy guy, I've not done it yet and this is the reason for which there are red balls on Hudson. What about providing some text console alternatives to installation? Also, the required Maven stuff is not available at the Central Repo and you have to install it manually on your repo - fortunately it's a straightforward process and you find step-by-step instructions in the maven-android-plugin docs and links.
- APIs not clean (--). This is the point that mostly stroke me. After so many year of bashing Swing for its 'old-style' and not completely congruent design, I really expected to find some super-clean-and-smart APIs in Android. This is not the case.
- For instance, you have a proliferation of 'int' constants - hey, Java 5 introduced enums! I don't think it's a big matter of performance...
- Also, you have to put casts where they could be avoided: a typical operation is to retrieve a pointer to a View object that has been declared in XML, such as TextView tv = (TextView)findViewById(R.id.some_id). Note that cast... of course, if the key is a f***ing plain 'int', there's no other way. But if the key were a generified object, the solution would be pretty easy as explained here.
- Also, I find that model classes are really poorly designed: for instance, a BaseAdapter and related classes, which is used as the model for many Views, is both a model in the strict-sense (it contains the data) and the factory for some parts of the UI (e.g. controls how a single row of a ListView is rendered, à la Swing ListCellRenderedFactory). Two very different responsibilities in the same class.
- Last but not least, still too much inheritance around: Activities are one of the most important parts in the model, and you have to override life-cycle methods. In 2010, I'd have expected e.g. simple aspects on side-classes based on annotations, such as it happens for some parts of the EJB APIs.
- I'd also have to say that some classes in the runtime (such as those related to the UI) are very bloated with methods. I suppose that there's no other practical way to do in a runtime, but I've been hearing Swing being constantly bashed for years.
- No binding out of the box (--). Another step-back (both from Swing and JavaFX) is that there's apparently no automatic binding of bound properties. For instance, I'd like to have TextView contents to be bound to a model, possibly with string interpolation. Fortunately, the java.beans.* stuff is here, so I could have some luck with BetterBeansBinding (thanks also to the fact that I've split the original BeansBinding in a core part where there are no Swing dependencies). Crossing fingers.
- High-level workflow model (++). One of the big differences from JavaFX Mobile is that you have rich components out-of-the-box (such as ListViews with scrolling effects, textual filtering, helper cursor for large scrolls, etc...) and, above all, a comprehensive workflow model (e.g. activities, tasks, intents) that pervades the whole appliance. A non-secondary point is that the model really fosters re-use and cooperation among different applications, a thing that in JME is very hard or practically impossible to do (in function of the available JSRs). This also means that it's much easier to produce applications with a consistent style - that's the key point to compete with the iPhone. I understand that it's more difficult for JavaFX to do the same, since it must run on multiple operating systems... but it's something that has to be done. For instance, in the hope of having a JavaFX port to Android, I'd like to see a specific library for the specific Android workflow.
- Pretty styled by default (++). In a completely different fashion than Swing, and partly also than JavaFX, things that you do in Android get a stylish (and consistent) l&f by default, even though you don't have studied the UI design guidelines yet. This is a fundamental point for end-users applications!
- Reinventing the wheel (---). Three minus, even though in the end is a minor point, because of the deliberate Android dumbness and the large frustration induced to the developer. For instance, look at the Location API (android.location). You'll find extremely similar stuff to javax.microedition.location! Was really so hard to reuse the classes? At least the model classes, such as Coordinate and such! Shame on Google!
- Fast compile-deploy-debug cycle (++). There are no significant time overhead when compiling (at least with Maven) and deployment to the emulator is fast. Furthermore, with my Motorola Droid and an USB connection, the deployment is equally fast and I can work in sustained mode with the real thing; redeployment is also consistent (it always works, not requiring cleaning actions, resets, etc...). This is a very different experience with all the other mobile gear I've owned and own.
- Quirks in the emulator (--). On the other hand, the emulator runtime is not bug free. Call me unlucky, but one of the first things that I faced with is that the JSON API seems to be just stubbed in the emulator. This frustrated me a bit as I started my work by first reimporting the real (and large) data model in the application, to be able since from the start to see how fast and effective was browsing into it. This was solved as I imported into the project the very light JSON/ME library, that also runs on JME and so should guarantee the portability of the code to JME. Also, Android has probably got the n+1 variation on the JSON APIs, just another reinvented wheel.
That's enough, for now. Just to give a hint of the things that I'm going to study, the next problem will be persistence. At the moment, the data needed for the application (a bird taxonomy) consists in a medium-size bag, that can be always parsed at boot from JSON and kept in memory. There are no queries, since it is only navigated in master-detail mode and the results are eventually simply filtered. Data inserted by users (bird observations) are not large and, at the moment, designed to stay for a short time on the application, as they will be soon shared with others by email or SMS. But in future it would be nice to be able to keep and sync a large database of stuff to be queried in a more sophisticated way. Keeping things tradictionally, Android has got SQLite and JDBC (but no JPA...); but I've already got an experience with a RDF store (OpenSesame) and not ony I've fully working code, but also the RDF stuff is much more suitable for a distributed, splittable and distributable database... Who knows if Android is enough for running it?
Also, I'd like to keep my design style - e.g. with composition and as(...); generally speaking, I hope to be able to reuse large parts of my stuff. One of the missing points is the NetBeans Lookup class. Maybe it runs out-of-the-box, or will I have to redesign it? Also, it would be nice to have it enhanced to work with Intents, that is part of the Android way to have modularity. Let's see...