BlackBerry API Hidden Gems (Part Two)

Java Development

In yesterday’s BlackBerry API Hidden Gems post, I showed you some of my favorite classes and methods oft overlooked within BlackBerry® APIs. I’ve got a few more in store for you today, so let’s get started!

IntVector

In the net.rim.device.api.util package there are a bunch of collections for storing primitive Java types, such as ‘int’, ‘byte’, and ‘long’, which mirror the equivalent java.util classes. Using these classes to store the primitive types is more efficient in both memory and time than storing wrapper objects in standard java.util collections.

My favourite example is IntVector. IntVector has the same methods as java.util.Vector but stores primitive ‘int’ values instead of Object references. Under the hood it uses an int[] array to store values instead of an Object[] array and therefore no conversions between ‘int’ and Integer are necessary. This makes IntVector much better for storing ‘int’ values than java.util.Vector as it is both faster and uses less memory. It is also fully synchronized, just like java.util.Vector.

Other adapted classes in net.rim.device.api.util include:

  • ByteVector and LongVector: similar to IntVector but for ‘byte’ and ‘long’ types.
  • IntHashtable, LongHashtable: adaptations of Hashtable that use primitive ‘int’ and ‘long’ values as the keys, and Objects as the values.
  • ToIntHashtable, ToLongHashtable: similar to IntHashtable and LongHashtable but uses Objects for the keys and ‘int’ and ‘long’ for the values.

Here is an example usage of IntVector to store a list of high scores, with the highest scores at the lowest indices.

public class HighScores {

private IntVector _scores;

public HighScores() {
_scores = new IntVector();
}

public void add(int score) {
if (_scores.contains(score)) {
return; // already there
}

boolean isAdded = false;
for (int i = 0; i < _scores.size(); i++) {
if (_scores.elementAt(i) < score) { _scores.insertElementAt(score, i); isAdded = true; break; } } if (!isAdded) { _scores.addElement(score); } while (_scores.size() > 10) {
_scores.removeElementAt(_scores.size() – 1);
}
}

public int getHighScore() {
if (_scores.isEmpty()) {
return 0;
} else {
return _scores.elementAt(0);
}
}

public int[] getHighScores() {
int[] array = new int[_scores.size()];
_scores.copyInto(array);
return array;
}
}

Timer and TimerTask

Like weak references, this next gem is also defined in CLDC but is mostly overlooked for its utility. Suppose you want to perform background tasks in your application. You can either use Application.invokeLater() or devise a grandiose background thread implementation that cleverly uses Java® synchronization primitives to efficiently perform background event dispatching. The former consumes your application’s event thread, potentially causing UI lag, and the latter is just a lot of work.

I recommend whipping out Timer and TimerTask for background task processing. Each Timer object has exactly one background thread which processes TimerTasks sequentially. These tasks can be scheduled to occur immediately, after some delay, at a particular time, or repeatedly at a given interval.

The sample below shows how to use Timer and TimerTask to notify an object on a non-event thread about the user pressing the trackball.

public class MyScreen extends net.rim.device.api.ui.container.MainScreen {

private Timer _timer;

public MyScreen() {
this.setTitle(“Timer Demo”);
this._timer = new Timer();
}

public void onTrackballClick() {
System.out.println(“Quit pressing the trackball!”);
}

protected boolean navigationClick(int status, int time) {
this._timer.schedule(new ClickTask(), 0);
return super.navigationClick(status, time);
}

private class ClickTask extends TimerTask {
public void run() {
onTrackballClick();
}
}
}

There are many more hidden gems in the BlackBerry® SDK but just not enough time here to share them all. I will be doing a talk on this topic at the 2009 BlackBerry Developer Conference and plan to talk about some hidden gems not mentioned here as well as some lesser-known cool features of the JDE itself. If you have found any hidden gems of your own please comment on this post to share your great discovery with the world! I’d love to know which APIs you find useful.

About Denver C.

Denver Coneybeare has worked for RIM since graduating from University of Waterloo in Waterloo, Ontario, Canada in 2005 with an Honors Computer Science degree. His roles at RIM have included automated API test developer, API designer and developer, and currently, Team Lead - Java Device APIs. Denver was drawn to API development by the unique challenges that public API design present, that simply are not there when developing code for one's own consumption. With a natural eye for usability, compatibility, and quality, the APIs that Denver has been in charge of are (in his own humble opinion) the best in the world... well, maybe not, but he thinks they're pretty good :)

Join the conversation

Show comments Hide comments
+ -
blog comments powered by Disqus