Skip to content

Development Concepts

jhugman edited this page May 31, 2012 · 3 revisions

Principles

Kirin tries hard to not get in the way. However, there are a number of principles that it encourages:

  • Each screen has two parts.
    • a native UI component, such as a UIViewController or android.app.Acitivity which draws pixels on the screen and catches events from the user. This is largely referred as the Screen.
    • a Javascript component which feeds the Screen data and acts upon events fed to it by the Screen. This is referred to as the Screen Module or more simply: the Module.
  • The lifecycle of the Javascript Module is driven by the Screen.
  • Every line of native code needs to be ported. This encourages you to minimize the complexity of the native code and push it into the Javascript.
  • The Javascript doesn't know what device it's on. This encourages you to have fewer fatter calls to the Screen and let the Screen display it in the manner it knows how too, and discourages over-fitting of the Javascript Module to the platform it's on.

These last two are in tension: avoiding overfitting leads to more native code, but the porting cost of native code leads us to want more Javascript.

Central Players

Native

There now follows a list of classes that you come in handy. Each has an implementation in iOS and Android.

Kirin

This is a singleton object that provides access to everything else. You will almost certainly never need to instantiate this.

KirinActivity or KirinUIViewController

In general, any native object can be exposed the Javascript, however Activities and UIViewControllers provide functionality to be called Screen objects.

These classes are convenient superclasses for you to extend to write your own screens.

If you use these as super-classes to your own screens, then construction of KirinHelper objects and lifecycles will be managed for you.

KirinHelper

These are the glue between Screen objects and Modules. These objects manage the bridge between native and Javascript.

The following exposes the this object to Javascript on Android:

// in MyScreenActivity.java, probably in onCreate()
mKirinHelper = getKirin().bindScreen(this, "MyModule");
mKirinHelper.onLoad();

The following is an equivalent in Objective-C:

// in MyScreenViewController.m, probably in viewDidLoad
self.kirinHelper = [KIRIN bindScreen: self withModule:@"MyModule"];
[self.kirinHelper onLoad];

The onLoad method gives the Javascript Module an object with all the same methods as the self or this native object.

The helpers also provide methods to call the Javascript methods of the Module.

For simple apps, the easiest way to start is to use:

    mKirinHelper.jsMethod("onConfirmValue", 123, "new value");

This executes code approximately equivalent to:

    require("MyModule").onConfirmValue(123, "new value");

This is a fairly low-tech way of calling Javascript, but is clear and understandable.

There are many types of KirinHelpers which correspond to the native object that you want to bind to Javascript. The KirinScreenHelper is the one a new app developer is most likely to start with.

Type safety

  • It is possible to arrange it so that the Javascript is achieved through generated proxy objects, which conform to a protocol. This is done via the kirinHelper, or through the screen's convenience super class (KirinUIViewController or KirinActivity).

Declare the screen's interface, that will be implemented by a Java object.

public interface IMyScreen {
  void displayTitle(String title);
}

Define the screen module's interface that will be implemented by a Javascript object.

public interface IMyScreenModule {
  void onConfirmValue(int id, String newValue);
}

In the Activity code, assume that we've wired up onButtonClick to be called in response to a button click.

public class MyScreenActivity extends KirinActivity implements IMyScreen {

  private IMyScreenModule mScreenModule;

  public onCreate() {
    super.onCreate();
    mScreenModule = bindScreen("MyModule", IMyScreenModule.class);
  }

  public onButtonClick() {
    // this is actually calling Javascript.
    mScreenModule.onConfirmValue(123, "new value");
  }
}

We can ease the burden of producing the interface and protocol files in sync, by using Kirin's [Interface Definition Language](Interface Definition Language).

Javascript

The Javascript environment is deliberately sparse; Kirin provides an implementation of CommonJS/Modules which is a way of providing per-file modularity. Other implementations of CommonJS Modules include: node.js, Couch DB. Kirin's implementation is provided by James Halliday's excellent browserify.

The following is a skeleton file that is suitable for binding to a screen. It includes all the lifecycle methods required a KirinScreenHelper needs.

/*
 *  This is the file MyModule.js
 * 
 */

// First up: lifecycle methods; these correspond to UIViewController and Activity lifecycles.

// this is the [proxy to the] native screen object.
var theScreen;

// this method is necessary iff you want to call out to native.
exports.onLoad = function (ui) {
  theScreen = ui;
};

exports.onResume = function () {
  // do something when the screen is about to appear
};

exports.onPause = function () {
  // do something when the screen is about to disappear
};

exports.onUnload = function () {
  // do something when the screen is unloaded. We probably won't do much here.
  theScreen = null;
};

// next: methods called by the UI, in response to events
// ...

The special exports object is made available to callers of require("MyModule");

Clone this wiki locally