Friday, January 20, 2012

Using Singleton Classes in BlackBerry JDE


Creative Commons Licence

This work is licenced under a Creative Commons Licence.

BlackBerry smartphone applications support multiple entry points. This is very handy for programers who want to provide a GUI application that also has a background processing component that listens for push data or some other useful function. This situation is complicated by the fact that each entry point is treated as its own process so classes get instantiated in separate address space. This is usually what the programmer wants, but occasionally we want to share the same object(s) between the two (or more) processes that make up a program. RIM recommends that you create a singleton class using the RuntimeStore

First the singleton class (borrowing from the RIM article on the subject, and the StackOverflow question that prompted this post):

import net.rim.device.api.system.*;

class MySingleton {
   private static MySingleton _instance;
   private static final long GUID = 0xabad1deaL;
private int i;

   // constructor
   MySingleton() {
      i = 0;
   }

   public static MySingleton getInstance() {
      if (_instance == null) {
         _instance = (MySingleton)RuntimeStore.getRuntimeStore().get(GUID);
      if (_instance == null) {

         MySingleton singleton = new MySingleton();

         RuntimeStore.getRuntimeStore().put(GUID, singleton);
         _instance = singleton;
         }
      }

      return _instance;

   }

   public synchronized int getI() {
     return i;
   }

 

   public synchronized void setI(int newI) {
      i = newI;
   }
 
   public synchronized int incI() {
      i++;
      return i;
   }
}

Next we define the main classes for the two entry points, the UI class defines the main, but it could be defined in the non-UI class:
import net.rim.device.api.system.*;

class MyUiClass extends UiApplication {

   public static void main(String argv[]) {
      // A simple way to differentiate between entry points is to call one with an argument and the other without
      // Auto-starting applications can have some other requirements that have to be followed, such as waiting for
      // the OS to complete booting so that networks, the UI and other needed services are available.

      if (argv.length > 0) {
         MyUiClass c = new MyUiClass();
         c.enterEventDispatcher();
      } else {
         MyClass c = new MyClass();
         c.enterEventDispatcher();
      }
   }

   private MySingleton _singleton;

   public MyUiClass() {
      _singleton = MySingleton.getInstance();
      // ToDo: initialize class to to the real work
   }

   public doSomthingToI() {
      _singleton.incI();
   }
}
and...
import net.rim.device.api.system.*;

class MyClass extends Application {

   private MySingleton _singleton;

   public MyClass() {
      _singleton = MySingleton.getInstance();
      // ToDo: initialize class to to the real work
   }

   public int getValueOfI() {
      return _singleton.getI();
   }
}

2 comments:

  1. Amazing explanation. This solved my problem perfectly!

    ReplyDelete