Smooth is one thing. Everything being functional is another.
It’s not GC pauses. It’s not because Android runs bytecode and iOS runs native code. It’s because on iOS all UI rendering occurs in a dedicated UI thread with real-time priority. On the other hand, Android follows the traditional PC model of rendering occurring on the main thread with normal priority.
This is a not an abstract or academic difference. You can see it for yourself. Grab your closest iPad or iPhone and open Safari. Start loading a complex web page like Facebook. Half way through loading, put your finger on the screen and move it around. All rendering instantly stops. The website will literally never load until you remove your finger. This is because the UI thread is intercepting all events and rendering the UI at real-time priority.
If you repeat this exercise on Android, you’ll notice that the browser will attempt to both animate the page and render the HTML, and do an ‘ok’ job at both. On Android, this a case where an efficient dual core processor really helps, which is why the Galaxy S II is famous for its smoothness.
On iOS when an app is installing from the app store and you put your finger on the screen, the installation instantly pauses until all rendering is finished. Android tries to do both at the same priority, so the frame rate suffers. Once you notice this happening, you’ll see it everywhere on an Android phone. Why is scrolling in the Movies app slow? Because movie cover thumbnails are dynamically added to the movie list as you scroll down, while on iOS they are lazily added after all scrolling stops.
I take back everything that I said about it being cooler that iOS feels smoother than Android.
I mean - the issue should certainly get fixed - with multicore processors they could just dedicate a core for UI rendering, which is impossible with the way it currently works. But now I understand why it happens.
EDIT:[Several people (+Chi-Ho Kwok and +Brent Royal-Gordon especially) have taken the time to explain some mistakes I made in my description of iOS. The fundamental distinction between Android and iOS rendering I identified still stands, but I made some over simpliifcations in my description of iOS because I wasn't familar enough with the workings. I'll let +Brent Royal-Gordon explain:
"The iOS description here isn't quite accurate. There are several things at work:
1. Compositing and previously set-up animations—all the stuff that involves the Core Animation rendering layer tree—do indeed happen on a background thread.
2. Drawing new content into Core Animation layers and setting up their animations happens on the main thread. This is the same thread that user interface actions occur on.
3. In naively written code, all developer-written code would occur on the main thread. However, Apple provides very easy APIs (Grand Central Dispatch and NSOperation) to move things into system-managed background threads. In iOS 5, you can even declare that a Core Data (object-relational database) context cannot be used directly on the main thread.
All that stuff you noticed—the way images aren't drawn into lists while you're scrolling, the way WebKit rendering stops when the system is tracking a touch—isn't inherently built-in by a mechanism that pauses the world when a finger is on the screen.* It's deliberate behavior painstakingly implemented by the developer of each individual app.
This is not a technical difference; it's a cultural difference. Good iOS developers don't ship software until it runs at something near 60 fps while scrolling and tracks touches almost perfectly; good Android developers do.
Going Forward
Android UI will never be completely smooth because of the design constraints I discussed at the beginning:
- UI rendering occurs on the main thread of an app
- UI rendering has normal priority
Even with a Galaxy Nexus, or the quad-core EeePad Transformer Prime, there is no way to guarantee a smooth frame rate if these two design constraints remain true. It’s telling that it takes the power of a Galaxy Nexus to approach the smoothness of a three year old iPhone. So why did the Android team design the rendering framework like this?
Work on Android started before the release of the iPhone, and at the time Android was designed to be a competitor to the Blackberry. The original Android prototype wasn’t a touch screen device. Android’s rendering trade-offs make sense for a keyboard and trackball device. When the iPhone came out, the Android team rushed to release a competitor product, but unfortunately it was too late to rewrite the UI framework.
This is the same reason why Windows Mobile 6.5, Blackberry OS, and Symbian have terrible touch screen performance. Like Android, they were not designed to prioritise UI rendering. Since the iPhone’s release, RIM, Microsoft, and Nokia have abandoned their mobile OS’s and started from scratch. Android is the only mobile OS left that existed pre-iPhone.
So, why doesn’t the Android team rewrite the rendering framework? I’ll let Romain Guy explain:
“...a lot of the work we have to do today is because of certain choices made years ago... ...having the UI thread handle animations is the biggest problem. We are working on other solutions to try to improve this (schedule drawing on vsync instead of block on vsync after drawing, possible use a separate rendering thread, etc.) An easy solution would of course to create a new UI toolkit but there are many downsides to this also.”
Romain doesn’t elaborate on what the downsides are, but it’s not difficult to speculate:
- All Apps would have to be re-written to support the new framework
- Android would need a legacy support mode for old apps
- Work on other Android features would be stalled while the new framework is developed
I can’t speak to the Android part, but I don’t think Andrew Munn is very familiar with iOS. UI rendering doesn’t happen on a background thread dedicated or otherwise, it happens on the main thread, and it doesn’t have anything to do with being “real-time” (unless you take that to mean “scheduled on a run loop”, which I don’t.) This is a big part of why Apple is constantly reminding developers to push anything they can into the background and leave the main thread free to draw and respond to user input. I would *love* for Apple to provide better support for drawing on background threads and/or in parallel, the only way to do it right now is using something called CATiledLayer but it’s very limited in scope and quite buggy.
Even though most of the iOS stuff in the post is wrong, Mr. Munn does a good job illustrating that the reasons behind Android’s perceived sluggishness are more complicated than a lack of hardware acceleration. All the hardware acceleration in the world won’t help a poorly written app on either platform, and UI responsiveness is a battle that has to be fought continuously using whatever tools are available.
It seems to me like the Android folk are a bit stuck in their ways and stubborn to change. While Casey always liked to mention that Android was in development before the iPhone, it's quite obvious that Android was built for non-touch screen devices and it shifted its strategy because of iPhone's release.