The *app.nit* application life-cycle is compatible with all target platforms.
It relies on the following sequence of events, represented here by their callback method name:
1 `on_create`: The application is being created.
You should build the UI at this time and launch services.
2 `on_resume`: The app enters the active state, it is in the foreground and interactive.
3 `on_pause`: The app becomes inactive and it leaves the foreground.
It may still be visible in the background.
4 `on_stop`: The app is completely hidden.
It may then be destroyed (without warning) or go back to the active state with `on_restart`.
5 `on_restart`: The app goes back to the inactive state.
You can revert what was done by `on_stop`.
Life-cycle events related to saving and restoring the application state are provided by two special callback methods:
* `on_save_state`: The app may be destroyed soon, save its state for a future `on_restore_state`.
There is more on how it can be done in the `app::data_store` section.
* `on_restore_state`: The app is launching, restore its state from a previous `on_save_state`.
These events are synchronized to the native platforms applications
The `App` instance is the first to be notified of these events.
Other UI elements, from the `ui` submodule, are notified of the same events using a simple depth first visit.
So all UI elements can react separately to live-cycle events.
The `app::ui` module defines an abstract API to build a portable graphical application.
The API is composed of interactive `Control`s, visible `View`s and an active `Window`.
Here is a subset of the most useful controls and views:
* The classic pushable `Button` with text (usually rectangular).
* `TextInput` is a field for the user to enter text.
* `HorizontalLayout` and `VerticalLayout` organize other controls in order.
Each control is notified of input events by callbacks to `on_event`.
All controls have observers that are also notified of the events.
So there is two ways to customize the behavior on a given event:
* Create a subclass of the wanted `Control`, let's say `Button`, and specialize `on_event`.
* Add an observer to a `Button` instance, and implement `on_event` in the observer.
The example at `examples/ui_example.nit` shows off most features of `app::ui` in a minimal program.
You can also take a look at the calculator (`../../examples/calculator/src/calculator.nit`) which is a concrete usage example.
You can go beyond the portable UI API of *app.nit* by using the natives services of a platform.
The suggested approach is to use platform specific modules to customize the application on a precise platform.
See the calculator example for an adaptation of the UI on Android,
the interesting module is in this repository at ../../examples/calculator/src/android_calculator.nit
Persistent State with data_store
*app.nit* offers the submodule `app::data_store` to easily save the application state and user preferences.
The service is accessible by the method `App::data_store`. The `DataStore` itself defines 2 methods:
* `DataStore::=` saves and associates any serializable instances to a `String` key.
Pass `null` to clear the value associated to a key.
* `DataStore::` returns the object associated to a `String` key.
It returns `null` if nothing is associated to the key.
redef class App
var user_name: String
redef fun on_save_state
app.data_store["first run"] = false
app.data_store["user name"] = user_name
super # call `on_save_state` on all attached instances of `AppComponent`
redef fun on_restore_state
var first_run = app.data_store["first run"]
if first_run != true then
print "It's the first run of this application"
var user_name = app.data_store["user name"]
if user_name isa String then
self.user_name = user_name
else self.user_name = "Undefined"
Async HTTP request
The module `app::http_request` provides services to execute asynchronous HTTP request.
The class `AsyncHttpRequest` hides the complex parallel logic and
lets the user implement methods acting only on the UI thread.
See the documentation of `AsyncHttpRequest` for more information and
the full example at `examples/http_request_example.nit`.
Compiling and Packaging an Application
The Nit compiler detects the target platform from the importations and generates the appropriate application format and package.
Applications using only the portable services of *app.nit* require some special care at compilation.
Such an application, let's say `calculator.nit`, does not depend on a specific platform and use the portable UI.
The target platform must be specified to the compiler for it to produce the correct application package.
There is two main ways to achieve this goal:
* The mixin option (`-m module`) imports an additional module before compiling.
It can be used to load platform specific implementations of the *app.nit* portable UI.~~~
# GNU/Linux version, using GTK
nitc calculator.nit -m linux
nitc calculator.nit -m android
nitc calculator.nit -m ios
* A common alternative for larger projects is to use platform specific modules.
Continuing with the calculator example, it is adapted for Android by the module `android_calculator.nit`.
This module imports both `calculator` and `android`, it can then use Android specific code.