Posterous theme by Cory Watilo

Work in Progress: In the Kirin Pipeline

We launched Kirin over the autumn of last year. For those who don’t know (which is most people), Kirin is a set of frameworks for writing cross platform native mobile apps.

I introduced Kirin to Over The Air, DroidCon London and DroidCon India by telling the story of how we wrote the now award winning Glastonbury 2011 app for Android, Qt and iOS.

Over the last 12 months we’ve gone from “That’s crazy, but it might well work”, through “Holy kaw, we’re doing it” to “it works, we should tell someone” and finally “if we could do it again, what would we change”.

Over the last three months or so, I’ve spent quite a bit of time asking folks who have looked at Kirin, some just a kick of the tyres, some been forced at knife-point to actually build something. Here’s what they’ve said:

  • getting started is way too hard.
  • there are too many dependencies
  • there is little or no documentation
  • there seems like there are many things to do, but I don’t know what they are.
  • there’s too much exposed, and the “API” for what it is, is not very well defined.
  • Android Fragments aren’t supported. There’s no point if fragments aren’t supported.
  • There’s a lot of Javascript. Does it have to be in Javascript?

Over the last month, we’ve started addressing these issues.

Now, I’m not ready to announce a big release, but I’m excited enough about what’s happening for me to talk about it now.

First off:

Modularizing the build

The aim of this piece of work is to minimize the number of dependencies you need in order to ship a product.

This is more of a problem than it sounds: there is a real cost to some of the dependencies.

  • iOS and Android both ship with SQLite. WP7 has a database, but it doesn’t speak SQL. We would likely need to ship SQLite for WP7.
  • Twitter and Facebook SDKs aren’t needed for many projects, so why is the Facebook SDK a requirement for Kirin on Android?
  • We don’t want to be the only ones able to add things into the Kirin codebase.

If we can make some parts of Kirin optional, then we can reduce the barrier to entry for new users, and at the same time giving a route to more advanced developers to extend Kirin in ways we haven’t thought of.

Part one of this work is now done: a spiffy new build script (I hesitate to call it a system), which gathers the Javascript together from the application, kirin-core and any plugins. The build is designed to be a little bit extensible, and we are also running native compilation through this as well.

It turned out that Javascript was a good language to write this in, and I made extensive usage of node.js’s fs and child_process modules.

Part two of this work will involve working out how to glue these so called plugins together. From a native compilation and project setup point of view, as well as a runtime configuration point of view.

Retooling for Android Fragments

Funnily enough, client needs mean that the fist thing to be done was for iOS.

However this is a hugely significant piece of work because it very much cleans up a lot of issues of code quality, object lifecycle, and leaky abstactions.

This work is mostly done for iOS now, but makes the previous incarnation of Kirin look like the prototype it really is.

Previously, Kirin was very much screen based – if you wanted to call out of Javascript to native you needed to find the currentScreenProxy which was left in a well known, but shared place.

var kirin = require("kirin");

exports.updateUi = function () {
    kirin.currentScreenProxy.updateUiWithData_(object);
}

Having to require("kirin") all over the place made testing difficult and caused problems with lifecycles which were akin to race conditions.

Now, the proxy for the native object is handed to the module at onLoad, which should happen at viewDidLoad: or onCreate() depending on what platform you’re on.

var theScreen;

exports.onLoad = function (ui) {
    theScreen = ui;
};

exports.updateUi = function () {
    theScreen.updateUiWithData_(object);
};

This should simplify mental models – you no longer need think in terms of “a proxy for the native object”, just “the object is passed to you”.

On the native side, calling Javascript was equally messy:

[KIRIN fireEventIntoJS:@"native2jsScreenProxy.onButtonClick()"];

This meant another object in global state, native2jsScreenProxy, and writing literal javascript code in app code, right in the middle of your native code.

It worked to prove a concept, but was never going to be something you’d want to live with.

Now we have a series of KirinHelper objects that manage a tight one-to-one relationship between a native object and a Javascript module.

These helpers manage the under-the-hood configuration needed to marshall the Javascript to Native communication, help manage the lifecycle of the Javascript modules, and are now the only way to call javascript modules and callbacks.

- (void) viewDidLoad {
    [super viewDidLoad];
    self.kirinHelper = [KIRIN bindScreen:self toModule:@"MyScreen"];
    [self.kirinHelper onLoad];
}

- (IBAction) onButtonClick: (UIButton*) button {
    [self.kirinHelper jsMethod: @"onButtonClick"];
}

Apart from elimiating the unsafe global state, it also gets rid of the awkward language of proxies and screens. This means that we can now use the same programming model of kirinHelper and injection for screens, custom components, platform services and Android Fragments.

The downside of this change is that we have had to break backwards compatability. Without compatible versions on other platforms, Kirin with Fragments is a cross-platform solution for a single platform. Android, then WP7, therefore, are a priority.

GWT

My colleague Mr. Hoskins is set to start this work very soon. This work is to make it possible to write as much (hopefully, all) of the shared code in your app in Java. Initially, this will be compiling down to Javascript to run in a browser for Android, but eventually, this will be running on Dalvik. I know he’s studying PlayN carefully.

This will be an optional component, so if you’d rather stick with Javascript you should be able to leave this alone.


Finally, we have a bunch of ideas for plugins, their implementations and their implications that we are quite excited by. For example:

  • re-using the work of node-browserify.
  • re-using PhoneGap plugins, particularly ones that didn’t use a WebView.
  • simplifying programming with services that need another screen.

That’s what’s happening to Kirin. I’m very excited by it. I hope to have more news… soon.