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

Categories : Java, Snippets, Tips, JME

Export this post as PDF document  Export this post to PDF document

Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!


Avatar: Evans

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!
Avatar: Peter Miklosko

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.
Avatar: Evans

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.
Avatar: Peter Miklosko

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
Avatar: Herman

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