Fabrizio Giudici is a Senior Java Architect with a long Java experience in the industrial field. He runs Tidalwave, his own consultancy company, and has contributed to Java success stories in a number of fields, including Formula One. Fabrizio often appears as a speaker at international Java conferences such as JavaOne and Devoxx and is member of JUG Milano and the NetBeans Dream Team. Fabrizio is a DZone MVB and is not an employee of DZone and has posted 67 posts at DZone. You can read more from them at their website. View Full User Profile

Newbie Understanding of Android

04.20.2010
| 14318 views |
  • submit to reddit

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...

Published at DZone with permission of Fabrizio Giudici, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Osvaldo Doederlein replied on Tue, 2010/04/20 - 8:01am

On the missing enum facility: in the JavaPosse list someone mentioned performance as excuse for no enums. I don't buy that because enums are just as efficient as ints - an enum-typed variable uses 32 bits (one object refernece), just the same size as an int variable. Of course the enumerated values are full-blown objects, and the enum class is bigger than an ints-collection pseudo enum class. But all these things are loaded/initialized/allocated only once, so it's just the static footprint that's bigger.

And considering that Google went through the trouble of designing their own classfile / bytecode / binary distribution format (.dex), they could have used the opportunity to fix this problem, by creating special support for enums. They could just define enum as a basic type -- not in the Java language typesystem to not increase the language fragmentation, but just in the VM level: have special field types and constant-pool types etc., so the encoding of a "real" enum class could be just as efficient as the encoding of an ints-collection clas, at least for trivial enums (those not containing user-defined fields and methods).

Sun always misses the opportunity to enhance the classfile/bytecode/jar formats in order to make the distributable binaries much more efficient: smaller to download, faster to load and verify, lighter on memory, easier to share btw processes, etc. They only do very conservative changes, like those in JSR-202. Many language features, from old ones (inner classes) to recent ones (enums), would benefit from first-class support from the bytecode spec. This would not only avoid convoluted translation techniques that produce bloated bytecode, but would also eliminate some screwups - e.g. inner classes spoil visibility of private class members (that are used from the inner class body) by adding non-private synthetic accessor methods. But Sun always has the excuse of legacy suppor, and need to ease the evolution of a gigantic toolchain and third-party utilities etc., to avoid radical improvements of the binary specs. Google didn't have this excuse, so IMHO it's a big #FAIL that Android didn't walk the extra mile when it introduced .dex.

Fabrizio Giudici replied on Tue, 2010/04/20 - 12:52pm

Yep, Osvaldo, the thought that Google wanted to change some things (for their own advantage) but missed to take the full opportunity out of them (from the bytecode stuff up to the APIs) is something that is always recurring to me as I learn Android more.

Artur Biesiadowski replied on Tue, 2010/04/20 - 1:12pm

@Osvaldo

Yes, it would be possible to create some kind of optimized support in .dex for initialization of enums, so the dex file size cost would be neglible. There is still a memory cost - in case of resource files, we are talking about hundreds, if not thousands objects to initialize and keep - but it is still in range of tens of kb.

Main issue in my option is cpu cost when you use actual enums. As you probably know, android phones do not have any jit support. Enums facility in java is depending on hotspot optimalizations very heavily to have same performance as plain ints

1) Retrieval of ordinal  is a method call, which is optimized away in hotspot, but still can be quite visible in embedded interpreter jvm - especially if you want few enums in inner loop for example.

2) Switch on enums (quite common), is represented as if/else if tree in bytecode, which can be easily order of magnitude slower than tableswitch for long cases. Again, hotspot is smart enough to understand this particular construct and convert it back to switch-like dispatch, but interpreted jvm is not.

If you would have true enums in such embedded technology, we would start seeing 'optimalization' guides, which would say you to retrieve ordinal value from enum outside of the loop and compare to local variable inside... to order switch cases on enums in the way that most common occurences are on the top... and it would be all true unfortunately, making applications measurably faster.

I think that having fast pseudo-enums ends up with cleaner code (taking lack of type safety into account) that what we would see with true enums and various hacks aimed at making them faster.

Tom Schindl replied on Tue, 2010/04/20 - 2:23pm

Just because you mentionned Databinding. This reminded me on http://tomsondev.bestsolution.at/2008/10/24/theres-no-place-where-eclipse-databinding-doesnt-work/.

Miguel Garcia-lopez replied on Tue, 2010/04/20 - 3:07pm

Fabrizio, this is a great post, full of information. Sure birds are glad such a smart observer devotes time to them :) Thanks and congrats, your articles are always a great read!

Alex(JAlexoid) ... replied on Tue, 2010/04/20 - 3:13pm

@Fabrizio

I really expected to find some super-clean-and-smart APIs in Android

Maybe you were also one of the people who thought that iPad is magic?

  • 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...

Since you don't think, maybe you should investigate. Int's are still far more efficient than enums(specially considering that it's run on DalvikVM). And every other point in your list just smells of lack of understanding. Android is usable because no one on that team listened to complaints like yours. Try doing reflection on every corner and see how well your application preforms on a HTC Magic(a.k.a Android Developer Phone 2).

If Android would have had the luxury of JIT and HotSpot, then your points would have been more relevant, but now they just look like "Newbie Rants about Android"(not the whole post though, only the API part).

PS: Let's not forget that Sun(Oracle) did not relinquish tight control over JavaME and Android's Dalvik VM is NOT Java(TM).

PPS: I develop for Android and after horrors of Swing it's a breath of fresh air.

See www.dalvikvm.com for more info on what and why.

Fabrizio Giudici replied on Wed, 2010/04/21 - 3:38am

I think that the enum things could have been solved anyway. Google could define two overloaded versions of findViewById(), one accepting an enum and one accepting an int. Then, enums used as API constants could have a special annotation to mark them for a special treatment I'm going to describe and have a property getter such as getCode() that returns the current int constant. In the end, since Android translates bytecode into Dalvik, a bytecode manipulator could replace all the findViewById(enum) into the corresponding findViewById(int) inlining the getCode() extraction. In this way, ranting people like me would be happy, and the generated Dalvik code would be just the same as today, with zero impact at runtime (at least for the two points mentioned by Artur) and a very slight overhead during compilation. BTW, one could even not use enum in this case (after all, the real usage is getting the getCode() value, and we don't need ordinal(), or the static values() etc), just a specific generified Key object wrapping an integer code and avoiding the cast - the special annotation would just instruct the code manipulator to do the trick. Do you see any problem with this approach?

For what concerns the aspect-via-annotations etc, I'm keeping very generic, but I still think that some solution that can be entirely applied during compilation (i.e. with an annotation processor) could work. This could be done by anybody of us, since it doesn't require changes to the Android runtime. I could work on this after I have matured more experience with the APIs and figured out how I'd like to see the code.

As per the ranting API, yes, I'm keeping the right of ranting back as I'm a happy Swing user :-) Of course I reckon that the Swing APIs are in large parts obsolete as per 2010 standards, but I'm just applying the same bashing standard to Android.

Glad to know about the Eclipse UFaceKit and going to have a look at it - in particular, if they provide JavaBean-compatible wrappers, BetterBeansBinding should work too.

Of course, it's clearly stated (even in the title, thanks to our magnific editors here at DZone) that this is a newbye perspective, with all the limits in it. I could change my mind with time on some parts, and I'll let you know.

Fabrizio Giudici replied on Wed, 2010/04/21 - 4:16am

PS That would be a generic way of handling enums in Android API calls (it could be applied even for constants used as various arguments of other methods). Needless to say that instead of doing Button bt = findViewById(R.id.bt) I would really like to have an @Inject @AndroidResource(R.id.bt) private Button bt (or @Inject @AndroidResource(R.id.bt) private Provider<Button> bt; for lazy loading) and, again, this could be handled by code generated during the compilation without impact at runtime (@AndroidResource would be a @Qualifier, a thing already in the @Inject specs).

Dan Bornstein replied on Wed, 2010/04/21 - 3:46pm in response to: Osvaldo Doederlein

Hi. I'm the primary designer of the .dex file format. First and foremost, thanks for the feedback.

In fact, lots of possibilities were on the table when the format was being designed, including special support for enums. However, we had neither infinite staff nor infinite time to accomplish all the design possibilities we explored. Furthermore, some things were simply off the table because we were adamant about taking .class files as input for translation and not trying to make a special source compiler. I hope the alternate-language crowd, in particular, appreciates that decision!

As you can imagine, much of the design was about trying to minimize size, and to give you an idea about where we drew the line, one of the last major format features we added was compact representation for initialized arrays of primitives (e.g., "byte[] blort = { 10, 20, 30 };"). The .class bytecode for these is super-bloaty and fairly slow, and we felt it was important to make the size of the representation be minimally larger than the simple size of the data and to make initilization reasonably close in performance to a simple memcpy(). Thankfully, we achieved both aims.

I freely admit that there are other valid tradeoffs that could have been made given our time and manpower constraints, but it saddens me to see our choices being painted simply as an unequivocal "big #FAIL."

In re the later comment pointing people at dalvikvm.com, that site isn't run by the Android project and had out-of-date and incomplete information the last time I checked. You can find extensive up-to-date documentation for the dex format in the Android sources under dalvik/docs.

Best regards.

 

ff aaa replied on Thu, 2010/04/22 - 12:58am

i still wonder. was it really necessary to make a new VM? i doubt that initial justification still make sense.

Hans Reiser replied on Thu, 2010/04/22 - 3:19am

@Alex(JAlexoid) WOW, what an elegant and respective style... given that you do not think, perhaps you should also investigate on your bon ton... are you always so friendly when you explain your point of view ?

Dan Bornstein replied on Thu, 2010/04/22 - 5:10pm in response to: ff aaa

In a word (or two), it does. The low-end of hardware that Android aims at still has severe constraints in terms of flash space, RAM, and CPU speed. Even the high end is significantly constrained in those regards. And the entire spectrum has power-consumption and bandwidth constraints.

The Dalvik .dex format provides for compact distribution, memory-mapped execution and other RAM-saving measures, and fast interpretation; and it is a sound basis for low-overhead JIT compilation (that is, lots of performance bang for little RAM and battery buck).

Of course, with each passing day, this year's low-end mobile hardware looks in many ways more and more like yesteryear's supercomputer (except for that pesky battery thing), and I expect the VM design and implementation will continue to evolve to match the changing shape of the constraints.

Best regards.

Jesse Wilson replied on Fri, 2010/04/23 - 3:05am

With respect to your JSON problems...

The android.jar is contains only stubs. It's useful for compiling against, but you shouldn't ever load it into a VM at runtime; dalvik or otherwise. When you include android.jar on your classpath, you'll run into stubbed method errors at runtime. This applies to code in org.json, android.util, ... the works. You won't run into problems for classes in java.* packages, but only because those packages are already built into your VM.

Writing code for Android and testing it on a desktop VM is possible, but I'm not aware of any tools that make it particularly easy. Sorry about that.

As a workaround, you can download the 5 .java files of org.json source from Android's git server, make a .jar out of 'em, and include that in your test classpath.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.