Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Big designs for small devices

Four J2ME design patterns simplify interactive content development

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 3 of 4

Wizard Dialog pattern

Many desktop applications use wizards in installation tools or configuration tools. In a wizard application, users are prompted through a series of screens. Each screen asks one or two questions. Two actions are allowed in wizard applications: Next and Back actions. Users press the Next button to proceed to the next screen. Users press the Back button to return to the previous screen and alter a previous answer. On mobile devices, wizard-style interaction involves a wireless application asking a series of questions to gather user input before performing an action. This is essentially a replacement for a Web input form, which doesn't fit well on mobile devices.

Let's look at an example—a local restaurant's search tool. This search tool uses city names and keywords as search criteria. The wizard application is implemented in two different Form classes. One Form contains a ChoiceGroup with a list of predefined city names. Another Form contains a TextField for users to input keywords. Each Form must have a Back command and Next command for navigation between pages. To make this example more interesting, users must enter as least three characters in the keyword input field.

Figure 3. A sample wizard application

A wizard application consists of several dialogs, all of which are linked sequentially by Back and Next commands. An important requirement is to allow developers to decouple these Forms from each other and control the screen flow separately. Developers should focus only on building the dialogs' content, not on the repeated components that control the flow. Another pattern, the Mediator pattern, provides a clean and elegant way to achieve this. A mediator is a middleman component that controls several related components. Figure 4 shows the Wizard Dialog pattern's UML diagram. The mediator is the WizardEngine class, and each individual dialog is a WDialog subclass. By subclassing the WDialog class, developers can focus their efforts on building the wizard's content. WizardEngine handles the screen flow automatically.

Figure 4. Wizard Dialog UML diagram

The WDialog class is an abstract subclass for the MIDP Form class. It allows your application to manipulate the WDialog as an ordinary Form object. When subclassing the WDialog class, you must implement an abstract method, initDialog(). The method's implementation builds the Form's screen content for gathering user input. The following is an initDialog() example that builds a form to prompt for city names selection.

Listing 3. initDialog() implementation that prompts for city names

public class WPage2 extends WDialog
{
   ChoiceGroup question1;
   
   public void initDialog()
   {
      setTitle("Step 2");
      
      question1 = new ChoiceGroup("Select a city name to search", ChoiceGroup.EXCLUSIVE, new String[]{"Toronto", "Ottawa", "Waterloo"}, null );
      
      append( question1 );
   }
}


Oftentimes, an application needs to validate user input before proceeding to the wizard's next screen. In our example, we require users to enter at least three characters for the keyword field. WDialog provides optional onEnter() and onLeave() methods for implementing data validation. The onLeave() method invokes every time a user moves to the next screen. An onLeave() implementation checks the data inputted by a user on the current screen. If the data is not valid according to its business rules, onLeave() returns WDialog.REJECT; otherwise it returns WDialog.OK. The framework will ensure the user cannot flip to the next screen if WDialog.REJECT is returned.

Similarly, the onEnter() method invokes when a WDialog screen is about to appear on the device. If this screen is ready to be shown, WDialog.OK is returned; otherwise, WDialog.REJECT is returned, and the framework will take the user back to the previous screen. The mechanism provides opportunities for a WDialog implementation to validate the prerequisites and post-requisites of entering and leaving a screen. The following is an example of onLeave() that checks the keyword field. An alert screen displays if the user enters less than three characters.

Listing 4. onLeave() implementation that checks for keywords

   public int onLeave( int dir )
   {
      if ( dir == WDialog.FORWARD )
      {
         // Question2 is a text box
         String answer = question2.getString();
         // Make sure user has entered 3 characters, and set the answer to a global variable
         if ( answer.length() < 3 )
         {
            // Show an alert screen
            Alert alert = new Alert("Bad Inpt");
            alert.setString( "You must enter at least 3 characters for keyword" );
            super.engine.getDisplay().setCurrent( alert, this );
            return WDialog.REJECT;
         } else
         {
            Wizardlet.answer2 = answer;
            return WDialog.OK;
         }
      } else
         return OK;
   }


The Wizard Dialog pattern allows developers to focus on their applications' user experience and screen flow, rather than on the wizard application's screen-by-screen wiring. Not only does Wizard Dialog save development time, it also reduces coding errors.

Pagination pattern

Mobile devices obviously have very limited screen real estate; they usually hold less than 10 lines of text. In many mobile applications, pagination is a hideous process. During pagination, large content pages break into multiple smaller pages; each contains a subset of the complete content. Users view the complete content by paging through the subset using a More or Next command.

In our restaurant search example, a wide search may result in 200 matches. This can divide into 10 pages, each page containing 20 matches in the list. Applications with pagination are more user friendly than those without because it takes less keystrokes to reach the target item. In some devices, pagination is also necessary for performance reasons. I have seen developers put 1,000 items in a single MIDP List, and the target phone consequently cannot respond to a single request. It takes a lot of memory and processing power to show 1,000 strings on a mobile phone.

The Pagination pattern provides a component that automates the paging process. This pattern also creates a clear separation between the data model and the view component. The data model in this case is the complete dataset (e.g., the 200 search matches). The data model does not need to know how the data breaks up to fit the display. The view component creates multiple content pages from the complete dataset. This is similar to a graphical user interface (GUI) toolkit (view) automatically providing a scroll bar to scroll a large image (the data) on a desktop application.

Figure 5. Pagination UML diagram

The Pagination pattern is a viewer-specific pattern that can be fully implemented in one class, PagableList. PagableList is a MIDP List subclass. Your application can treat this as an ordinary List class and perform usual List operations on it. You can add items and commands, and register command listeners. But it is not an ordinary List on the inside.

PagableList is a proxy to the original List because it overrides some of the methods. Internally, it holds the entire dataset and manages a sublist of it. It maintains a cursor that points to the currently displayed sublist index. It registers two built-in commands: the More and Previous commands. When users hit the More command, PagableList automatically advances to the next set of sublists and displays them on the screen. Similarly, when users hit the Previous command, PagableList rolls the cursor back to the previous dataset and puts them on the screen. By managing an internal cursor, users can quickly page through each data subset.

PagableList is a ready-to-use component. No additional work is required to enable pagination for your application. You simply create an instance of PagableList instead of a List and add data to it using the append() method. Since PagableList is a List subclass, it supports all List behavior, and you can cast its type into List throughout your application. This code fragment shows how to use PagableList:

Listing 5. PagableList sample usage

   PagableList pagablelist = new PagableList( "Paging", List.IMPLICIT);
   
   // 'this' refer to the current MIDlet
   Display.getDisplay(this).setCurrent(pagablelist);
   
   for ( int i=0; i< 100; i++ )
   {
      pagablelist.append( "Item  #"+i, null );
   }


PagableList implements a proxy pattern. By encapsulating the original List from the outside, PagableList puts additional functionality on top of List. The original proxy pattern suggests encapsulation by using a placeholder to control access to the subject. I modify it to include encapsulation by subclassing and overriding the List's interface. This approach allows me to preserve List's interface and type hierarchy, making it easier to use and lowering this pattern's overhead. Small optimizations like this can greatly improve design pattern usage in constrained J2ME environments.

Slide Show pattern

A slide show is another common form of interactive content usually viewed on desktops. A slide show is a sequence of screens that displays in a specific order. Each slide contains texts, images, or a mixture of both. For this article's purpose, we only consider the autopilot-mode slide show. The sequence appears as it is programmed; users cannot control the sequence's pace or order. A pause occurs between each slide so users have enough time to view and read a slide's content. The application controls the slide show's start and stop. The slide show also stops when it reaches the end of the sequence. The slide show requires the ability to add and remove slides easily without impacting other slides already implemented. The dependency between slides must be minimal.

Figure 6. Example slide show sequence

Similar to the Wizard Dialog solution previously discussed, a mediator flexibly decouples related screens. A slide show application shares some similarities with a wizard application in that they both involve multiple screen displays. In this solution, we encapsulate all the slide show's behavior into one class: SlideEngine. The SlideEngine class is an execution engine of the slide show sequence. Each slide is an implementation of the MIDP Displayable class. For text slides, we use TextBox. For image slides, we use Form with ImageItems or a custom Canvas implementation. Since every slide must be set into the Display object to display on a device screen, SlideEngine also holds a reference to the current MIDlet Display object during initialization. A sequence is a series of alternating Displayable objects. A time interval representing each slide's display duration follows each Displayble object (slide). The longer the interval, the longer a slide stays before the next slide displays. Let's put all these requirements into a UML diagram.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (1)
Login
Forgot your account info?

list code for nokia 3210By Anonymous on October 23, 2008, 2:44 amlist code for nokia 3210

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources