<< Contact sorting - Contact List, Part 3 | Home | How to browse file structure of mobile device with JME >>

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 from

    Display.getDisplay(imageHttp.ImageHttp.instance).setCurrent(dis);

    to

    ImageHttp.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 as

    mgr.chamgeScreen("imageHttp.gui.ImageUrlRequest");

    and by adding constants to interface

    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";

    screen changes can be reduced to

    mrg.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 modifier

    public 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); } } }



Re: Display - Best Practice (hopefully)

Nice piece of blog post - It would have been much better if you added a screen shot to illustrate your result. Otherwise, you've done a marvellous job!

Re: Display - Best Practice (hopefully)

Thank you Evans. I try to post things that can be helpful to students. Things that are not normally discussed in book in details or tutor/teacher at school cannot provide sufficient explanation.

off topic

Thanks for the comment on my blog. You made a very valid point - I will start changing the link attributes to open up in a new tab/windows instead of leaving my blog. BTW, we had a smashing Android event on Thursday.

off topic

The event in Google office by Reto started little later then expected, but he and another chap from Google made very good presentation plus there was plenty of pizza and free drinks :D

Re: Display - Best Practice (hopefully)

hi, I'm new to J2Me and also in search of good pratice of screen changing, and your post are surely inspiring :) it does have a problem if we want to initialize the displayble though, like if we want to set the title for the next screen. perhaps the changeScreen should return the displayble so we could do some initialization. public Displayable changeScreen(String _uiClass) { Displayable display = null; try { display = (Displayable) Class.forName(_uiClass).newInstance(); disp.setCurrent(display); ((CoreUI) display).setUIManager(this); } catch (Exception e) { e.printStackTrace(); } return display; } public void showForm() { Form form = (Form)changeScreen(MAIN_FORM); form.setTitle("my form"); }

Add a comment Send a TrackBack