Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Posts: 87
Registered: ‎08-25-2009
My Device: Not Specified
Accepted Solution

Painting hidden fields on Screen

Hi,

 

I have a screen that adds custom fields to itself. The custom fields contain some information downloaded before loading the screen, and an image that is downloaded from a PHP script, when the field is painted. Currently, what happens is that when you scroll down, and a new Field is revealed, it executes the paint method, which downloads the picture and stores it in memory.

 

What I want to do is have a default picture for all the objects, and have two threads: one that downloads the pictures while the user is using this Screen, and another thread that repaints the Fields if their images have been downloaded. This is the code that sets up the screen:

 

 

public void CreateIncidentList(ResponseGroup rg) {
for (int i = 0; i < rg.getIncidentsUBound(); i++) {
IncidentListItem ili;
try {
ili = new IncidentListItem(rg.getIncident(i));
add(ili);
//ili.invalidateLaneBitmap(); //XXX: Do we need to do this to force it to paint blank lanes the first time?
} catch (Exception e) {
continue;
}
if (i < (rg.getIncidentsUBound() - 1)){
add(new SeparatorField());
}
}

threadLaneBitmapDownloader = new Thread(LaneDownloader);
threadLaneBitmapRepainter = new Thread(LaneRepainter);
threadLaneBitmapDownloader.start();
threadLaneBitmapRepainter.start();
try {
threadLaneBitmapDownloader.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
threadLaneBitmapRepainter.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Here is the Downloader Runnable:

 

private Runnable LaneDownloader = new Runnable(){

public void run() {
	//Manager m = me.getMainManager();
	int numIncidentListItems = getFieldCount();
	IncidentListItem ili;
	Incident i;
	
	for(int x = 0; x < numIncidentListItems; x++){
		try{
			ili = (IncidentListItem) getField(x);
			i = ili.getIncident();
			for(int counter = 0; counter < i.getUBoundLocalIncidentInformation(); counter++){
				if(i.getLocalIncidentInformation(counter).getLaneBitmap() == LocalIncidentInformation.blankLane){
					i.getLocalIncidentInformation(counter).downloadLaneBitmap();
				}
			}
		} catch (ClassCastException e){
			continue;
		}
	}
}
	
};

 

 

 

Here is the Repainter Runnable:

 

 

private Runnable LaneRepainter = new Runnable(){

public void run() {
while(threadLaneBitmapDownloader.isAlive()){
Manager m = me.getMainManager(); //Don't know if this is correct!
int numIncidentListItems = getFieldCount();
IncidentListItem ili;
Incident i;

for(int x = 0; x < numIncidentListItems; x++){
try{
ili = (IncidentListItem) getField(x);
i = ili.getIncident();
if(ili.getPaintedLaneBitmap() == LocalIncidentInformation.blankLane){
final IncidentListItem mIli = ili;
UiApplication.getUiApplication().invokeAndWait(new Runnable(){
public void run () {
mIli.invalidateLaneBitmap();
mIli.setPaintedLaneBitmap(mIli.getIncident().getLocalIncidentInformation(0).getLaneBitmap());
}
});
}
try {
Thread.sleep(100);
}
catch (InterruptedException ioe) {
System.out.println(ioe.getMessage());
}

} catch (ClassCastException e){
continue;
}
}
}
}

};

 

What I want to accomplish is to let the user scroll through the Fields while the pictures are downloaded and refreshing while they are scrolling. IncidentListItems are field wrappers for Incident objects which is where the picture is stored. Also there is a field called paintedLaneBitmap, which is supposed to store the image that was painted when the IncidentListObject is created. This normally should be the blankLane image. So the idea is that, one thread downloads the pictures in the background, and another thread checks to see if the Incident object's laneBitmap of the IncidentListItem is different from the painted object, and repaint the Field.

 

How can I accomplish this?

Thanks so much in advance.

 

 

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Painting hidden fields on Screen

Sorry I've not even looked at your code because I would actually do what you want a different way.

 

Here is a quick suggestion.

 

Have one Thread that processes your downloads.  It works off a queue, you add the pictures you want it to download into the queue. 

 

The Queue is just a vector of Objects.  Each object contains enough information for the downloader to get and store the image somewhere useful.  It also has a 'Runnable'.  The Runnable is responsible for updating the Screen.

 

So when your Thread finishes downloading a picture, it just does an invokeLater on the Runnable, which is then responsible for updating the screen.

 

So there is no polling, no looping, you use notify/wait on the download Thread so it doesn't use any resources unless there is work for it to do.

 

There are many many variations on this theme, but I hope this is enough to make you rethink how you processing works, so that it will do what you want in a more efficient way. 

 

Developer
Posts: 87
Registered: ‎08-25-2009
My Device: Not Specified

Re: Painting hidden fields on Screen

First off thanks so much for your reply.

 

So would you suggest I modify my code so that there is only one thread, that downloads and invokes InvokeLater when a download is complete, and scrap the other loop thread. I end the download thread when all of the images are downloaded. Should I loop through all the fields to see if all the Fields that should have a new image have one?

 

I've never used notify/wait before.

 

Also, how do I update the Fields in the screen that aren't visible?

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Painting hidden fields on Screen

If you wish to have a Thread that is specific to this screen, then what you are suggesting makes sense.  Looping through the Fields makes sense too.  Using this approach you do not need to use wait/notify. 

 

The approach I had described could be used as a generic solution in other places.

 

I'm not sure what you mean by Fields that are not visible.  If you update an offscreen image, the UI processing will probably just ignore your change.