Display - Best Practice (hopefully)
How-To manage display change from screen to screen
For some time I was happy with the way I've written the code to handle showing information on device display. This topic was not discussed at my university, I guess no one actually does it, we were just provided with sample application that did whatever task been showcased during the lecture. Same applies to books that I've read so far, in regards to mobile development ( Beginning J2ME: From Novice to Professional, Kicking Butt with MIDP and MSA - Creating Great Mobile Applications, Enterprise J2ME Wireless Applications and J2ME in a Nutshell), not one of them actually explained how display changing action should be performed. After recently starting to study for my SCJP exam (SCJP Sun Certified Programmer) I asked my self "Do I really do it the best way?".
So I went and asked around if my approach was any good. Here is the code as I submitted it for discussion:
ImageHttp.java
package imageHttp;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import imageHttp.gui.MainMenu;
public class ImageHttp extends MIDlet{
public static ImageHttp instance;
private MainMenu mMenu;
public ImageHttp(){
instance = this;
}
public void startApp(){
if(mMenu == null){
mMenu = new MainMenu();
}
Display.getDisplay(this).setCurrent(mMenu);
}
public void pauseApp(){}
public void destroyApp(boolean unconditional){}
public static void quitApp(){
instance.destroyApp(true);
instance.notifyDestroyed();
instance = null;
}
}
MainMenu.java
package imageHttp.gui;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
public class MainMenu extends List implements CommandListener{
private final Command exitCom;
public MainMenu(){
super("Image Up/Down-load", List.IMPLICIT);
exitCom = new Command("Exit",Command.EXIT,0);
addCommand(exitCom);
setCommandListener(this);
}
public void commandAction(Command c, Displayable d){
if(c == exitCom){
imageHttp.ImageHttp.quitApp();
}
else{
int index = getSelectedIndex();
Displayable dis = null;
switch(index){
case 0:
dis = new ImageUrlRequest();
break;
case 1:
dis = new ImageServletRequest();
break;
case 2:
dis = new ImageUpload();
break;
default:
break;
}
Display.getDisplay(imageHttp.ImageHttp.instance).setCurrent(dis);
}
}
}
I made number of posts on various forums, where most of people nailed my use of static instance and recommended to provide some getter method to be able access MIDlet directly. Something like
public Display getDisplay () {
return Display.getDisplay(this);
}
However nobody come forward with something more exciting untill I received detailed explanation and recommedation from sfitzjava at forums.java.net.- Introduce instance variable of
private Display disp = Display.getDisplay(this);
- Provide a method to change the current screen
public void changeScreen(Displayable _ui){ disp.setCurrent(_ui); }
In doing so screen logic changes fromDisplay.getDisplay(imageHttp.ImageHttp.instance).setCurrent(dis);
toImageHttp.instance.changeScreen(disp);
- To remove dependecy on static variable and static method linked with this variable introduce an interface with an instance variable of type ImageHttp (my MIDlet).
public interface CoreUI { void setUIManager(ImageHttp _mgr); }Implement the interface in any class that is participating in application GUI so screen changes are made asmgr.chamgeScreen("imageHttp.gui.ImageUrlRequest");and by adding constants to interfacepublic final String MAIN_MENU = "imageHttp.gui.MainMenu"; public final String URL_REQUEST = "imageHttp.gui.ImageUrlRequest"; public final String SERVLET_REQUEST = "imageHttp.gui.ImageServletRequest"; public final String UPLOAD = "imageHttp.gui.ImageUpload";
screen changes can be reduced tomrg.changeScreen(CoreUI.URL_REQUEST);
- Now with all the changes in application subclasses MIDlet also need small make-over
public void changeScreen(String _uiClass){ Displayable display; try{ display = (Displayable)Class.forName(_uiClass).newInstance(); disp.setCurrent(display); ((CoreUI)display).setUIManager(this); } catch(Exception e){ e.printStackTrace(); } }small change for startApp()public void startApp(){ changeScreen(CoreUI.MAIN_MENU); } public void startApp(){ changeScreen(CoreUI.MAIN_MENU); }and freeing destroyApp() from static modifierpublic void quitApp(){ destroyApp(true); notifyDestroyed(); }
And here is final outcome
ImageHttp.java
package imageHttp;
/**
* Created by IntelliJ IDEA.
* User: Peter Miklosko
* URL: http://www.peterscorner.co.uk
* Date: 26-May-2009
* Time: 13:51:16
*/
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
public class ImageHttp extends MIDlet{
private Display disp = Display.getDisplay(this);
public ImageHttp(){}
public void startApp(){
changeScreen(CoreUI.MAIN_MENU);
}
public void pauseApp(){}
public void destroyApp(boolean unconditional){}
public void quitApp(){
destroyApp(true);
notifyDestroyed();
}
public void changeScreen(String _uiClass){
Displayable display;
try{
display = (Displayable)Class.forName(_uiClass).newInstance();
disp.setCurrent(display);
((CoreUI)display).setUIManager(this);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Interface CoreUI.java
package imageHttp;
/**
* Created by IntelliJ IDEA.
* User: Peter Miklosko
* URL: http://www.peterscorner.co.uk
* Date: 29-May-2009
* Time: 14:29:39
*/
public interface CoreUI {
public final String MAIN_MENU = "imageHttp.gui.MainMenu";
public final String URL_REQUEST = "imageHttp.gui.ImageUrlRequest";
public final String SERVLET_REQUEST = "imageHttp.gui.ImageServletRequest";
public final String UPLOAD = "imageHttp.gui.ImageUpload";
void setUIManager(ImageHttp _mgr);
}
MainMenu.java
package imageHttp.gui;
/**
* Created by IntelliJ IDEA.
* User: Peter Miklosko
* URL: http://www.peterscorner.co.uk
* Date: 26-May-2009
* Time: 13:52:42
*/
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import imageHttp.CoreUI;
import imageHttp.ImageHttp;
public class MainMenu extends List implements CommandListener, CoreUI{
private final Command exitCom;
private ImageHttp mgr;
public MainMenu(){
super("Image Up/Down-load", List.IMPLICIT);
}
public void setUIManager(ImageHttp _mgr){
mgr = _mgr;
init();
}
public void init(){
append("URL request down.", null);
append("Servlet request down.", null);
append("Http servlet up.", null);
exitCom = new Command("Exit",Command.EXIT,0);
addCommand(exitCom);
setCommandListener(this);
}
public void commandAction(Command c, Displayable d){
if(c == exitCom){
mgr.quitApp();
}
else{
int index = getSelectedIndex();
String dis = "";
switch(index){
case 0:
dis = CoreUI.URL_REQUEST;
break;
case 1:
dis = CoreUI.SERVLET_REQUEST;
break;
case 2:
dis = CoreUI.UPLOAD;
break;
default:
break;
}
mgr.changeScreen(dis);
}
}
}













