J2ME alapok: a MIDlet életciklusa, és miért fut le kétszer a startApp
Közzétéve:
Aki Symbian C++ után nyúl a Javához, először megkönnyebbül. Nincs cleanup stack, nincs kétfázisú konstruálás, és a program a legtöbb mai telefonon fut, nem csak a Series 60-asokon. A J2ME (pontosabban a CLDC konfiguráció és a MIDP profil) programjait MIDletnek hívják. A legfontosabb dolog, amit meg kell érteni róluk, az életciklusuk.
A három állapot
Egy MIDlet három állapotban lehet: szüneteltetett (paused), aktív (active) és megsemmisült (destroyed). Az állapotváltásokat a telefon szoftvere (az AMS, vagyis az alkalmazáskezelő) vezérli, és ilyenkor meghívja a MIDlet egy-egy metódusát:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ProgzMidlet extends MIDlet implements CommandListener {
private Form form;
private Command exit;
private boolean started = false;
public ProgzMidlet() {
form = new Form("Progz");
exit = new Command("Kilépés", Command.EXIT, 1);
form.addCommand(exit);
form.setCommandListener(this);
}
protected void startApp() throws MIDletStateChangeException {
if (!started) {
form.append("Szia, J2ME!");
started = true;
}
Display.getDisplay(this).setCurrent(form);
}
protected void pauseApp() {
// itt kell elengedni a szálakat, a hangot, a hálózatot
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
// mentés RMS-be, takarítás
}
public void commandAction(Command c, Displayable d) {
if (c == exit) {
try { destroyApp(true); } catch (MIDletStateChangeException e) { }
notifyDestroyed();
}
}
}
A kétszer lefutó startApp
A kezdők leggyakoribb hibája, hogy minden előkészítést a startApp-ba tesznek. Indításkor ez működik, de ha közben hívás érkezik, a telefon szünetelteti a programot (pauseApp), utána pedig újra meghívja a startApp-ot. Ilyenkor duplán jelennek meg a lista elemei, két szál indul, vagy elölről kezdődik a játék. A fenti kódban a started jelző véd ez ellen. A felületi elemek pedig eleve a konstruktorban jönnek létre.
Fontos az is, hogy a MIDlet saját magától nem lép ki. A kilépést a notifyDestroyed() jelzi az AMS-nek. A destroyApp csak egy kérés, hogy takarítsunk, ezért a fenti kód kézzel hívja meg kilépés előtt.
A JAD és a JAR
A lefordított és előellenőrzött (preverify) osztályok egy JAR-ba kerülnek, mellé pedig egy JAD leíró tartozik. Sok telefon először a JAD-ot tölti le, és ebből dönti el, hogy egyáltalán telepíthető-e a program:
MIDlet-Name: Progz Demo
MIDlet-Version: 1.0.0
MIDlet-Vendor: Progz
MIDlet-Jar-URL: progzdemo.jar
MIDlet-Jar-Size: 14823
MIDlet-1: Progz Demo, /icon.png, ProgzMidlet
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.0
A MIDlet-Jar-Size legyen bájtra pontos. A Wireless Toolkit (most a 2.2-es verziót használom) a Project → Package paranccsal ezt automatikusan kitölti. Ha viszont utólag kézzel cserélsz valamit a JAR-ban, ne felejtsd el átírni ezt a számot is.
Mit érdemes tesztelni?
Az emulátorban minden szép, a valóságban nem. Három dolgot próbálok ki minden készüléken: hívás közben szünetel-e rendesen a program, mi történik, ha a játék közben becsukják a kagylót, és mekkora a legnagyobb JAR, amelyet a telefon elfogad. Ez utóbbi régebbi készülékeken akár 64 KB alatt is lehet.