Implementing the MIDlet main classes

The MIDlet contains the following main classes:

MovieBookingMIDlet class

The MovieBookingMIDlet class contains the code specific to the MIDlet application model. The class extends SWTMIDlet and implements its runMain method. The SWTMIDlet class is part of the eSWT MIDlet starter used for creating eSWT UIs. The SWTMIDlet class fully manages the eSWT UI thread for the MIDlet, creating and starting it when the MIDlet is started, and terminating it when the user exits the MIDlet.

public class MovieBookingMIDlet extends SWTMIDlet {

    private MovieBooking bookingApp;

    protected void runMain() {
        bookingApp = new MovieBooking(this);
        bookingApp.run();
    }
}

MovieBooking class

The MovieBooking class is the starting point of the MIDlet UI. It contains the eSWT event loop and UI thread, creates the top-level Shell, and controls the application logic and other classes that build the UI. It performs all the state changes on the UI, and handles the movie database.

The MovieBooking class uses the Display and Shell classes to manage the connection between SWT and the underlying operating system, and to construct windows, respectively. Since this tutorial focuses on the eSWT features of the MIDlet rather than its business logic, the code that implements aspects of the Display and Shell classes is more extensively commented than the code related to the business logic.

The following are the key UI aspects to implement in the MovieBooking class:

  1. Set the MovieBooking class to implement Runnable and MovieDBListener. MIDlets use the Runnable interface to implement threads.

    public class MovieBooking implements Runnable, MovieDBListener {
  2. Implement the run method, which controls the UI thread and event loop, and accesses the system resources and the main Display (which is the parent of all other Displays).

        public void run() {
    
            running = true;
            // Note that Display has to be created here since that
            // determines the UI thread
            display = new Display();

    The display = new Display() code line constructs a new instance of the Display class. Note that this thread must dispose of the Display instance before it can construct another one. However, the instance must not be disposed of until the MIDlet is about to enter the Destroyed state.

  3. Create the top-level Shell. Note that when using eSWT, it is strongly recommended to have only one top-level Shell.

    The SWT class provides an optional, appearance-related SWT.NONE constant, which can differ between implementations.

            // Create the main shell
            mainShell = new Shell(display, SWT.NONE);
            mainShell.setText("MovieBooking");
  4. Use the mainShell.open method to place the main Shell at the top of the drawing order, mark it as visible, set the focus, and make it active.

            // Create a layout for the shell
            GridLayout layout = new GridLayout();
            // Zero the margins that are non-zero by default
            layout.horizontalSpacing = 0;
            layout.verticalSpacing = 0;
            layout.marginWidth = 0;
            layout.marginHeight = 0;
            mainShell.setLayout(layout);
    
            // open first this shell to be in the background
            mainShell.open();
            mainShell.setRedraw(false);
  5. Build the splash screen, and start loading the movie database.

            // Creates the splash screen
            splashScreen = new SplashScreen(this, mainShell);
    
            // Activate the layout of the mainShell to make it resize
            // the splashScreen
            mainShell.layout();
            mainShell.setRedraw(true);
            // Create the MovieDB and request that it starts loading the data
            movieDB = new MovieDB(getClass().getResourceAsStream(
                    "/res/movieDB.properties"));
            movieDB.setDBListener(this);
            // This starts loading the data on a separate thread
            movieDB.loadData();
  6. Create an event loop and run it until the main Shell is disposed of. You must execute an eSWT event loop in the run method and explicitly make it visible.

    Start the event loop after the UI has been built. The event loop continuously checks that the running variable is true and that the top Shell has not been disposed of. If the event loop finds events waiting in the event queue, it uses the display.readAndDispatch method to process and send them to their respective listeners. When there are no pending events left, the MIDlet calls the display.sleep method to release the main processor.

            // eSWT event loop runs until the main shell is disposed
            // or the running flag is set to false.
            // The flag can get set due to a user initiated exit or due to
            // a system request to terminate the application.
            while (running && !mainShell.isDisposed()) {
                // Check if there are pending events
                if (!display.readAndDispatch()) {
                    // otherwise sleep
                    display.sleep();
                }
            }
    
            // Dispose the display, this will also dispose mainShell
            display.dispose();
            // Destroy the MIDlet
            midlet.notifyDestroyed();
        }
  7. If the UI thread is in sleep mode, use the display.wake method to wake up the thread and start it running again.

        // Exit method
        public void exit() {
            // close the DB and dispose the main shell
            movieDB.close();
            running = false;
            display.wake();
        }
  8. To provide the user some information about the ongoing reservation process, use the MessageBox class.

        // Displays a message box
        int displayMessageBox(int type, String text, String message) {
            if (Thread.currentThread() == display.getThread()) {
                MessageBox box = new MessageBox(mainShell, type);
                box.setText(text);
                box.setMessage(message);
                return box.open();
            } else {
                return -1;
            }
        }