-
Notifications
You must be signed in to change notification settings - Fork 22
Development Concepts
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
orandroid.app.Acitivity
which draws pixels on the screen and catches events from the user. This is largely referred as theScreen
. - a Javascript component which feeds the
Screen
data and acts upon events fed to it by theScreen
. This is referred to as theScreen Module
or more simply: theModule
.
- a native UI component, such as a
- The lifecycle of the Javascript
Module
is driven by theScreen
. - 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 theScreen
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.
There now follows a list of classes that you come in handy. Each has an implementation in iOS and Android.
This is a singleton object that provides access to everything else. You will almost certainly never need to instantiate this.
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.
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.
- 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
orKirinActivity
).
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).
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");