I have just spent a week figuring out why my app, which works fine on smaller non-Nokia phones, kept running out of memory on the 3650. This was extremely frustrating because the 3650 is supposed to have gobs of memory. Anyway, I could rant for hours on all the things I had to try, but I now suspect the problem is the Nokia implementation of Canvas and FullCanvas. Let me explain.
In my app (a game) I have a class (called UICanvas) that extends FullCanvas (at least this was how is originally worked). Anyway, during the execution of my game, I would need to create numerous instances of UICanvas to display as part of the game. However, I kept running out of memory when doing this. I tried different tests extending either Canvas or FullCanvas, and the problem existed in both cases. I began to suspect a day ago that the problem was that maybe Nokia Canvas and FullCanvas secretly allocated their own big chunks of memory to store the last screen painted on them, should a user wish to return to the screen.
To test my theory, I rewrote my code so that now my UICanvas class does NOT extend either Canvas or FullCanvas. Instead I created a new class called FullCanvasImp that extends FullCanvas. FullCanvasImpl is a "bare bones" class that simply contains a reference to a UICanvas, and contains a paint() method that simply calles the paint method on the UICanvas object that is stored in the FullCanvasImpl object. (See code below). I changed UICanvas so that instead of extending FullCanvas, it just it just contains a static reference to a single instance of FullCanvasImpl, where this FullCanvasImpl instance is shared among all my UICanvas objects.
In other words, now my UICanvas object just contain the data needed to draw on a FullCanvas, but the actual FullCanvas object on which I draw the data is just this static instance of FullCanvasImpl.
The code to switch Displayables is bit more complicated now because the VM doesn't really think you are switching Displayables - it just thinks you are painting different things to the same Displayable (same FullCanvasImpl). This means that the VM does not automatically call showNotify or hideNotify, instead I had to do that manually inside a method I wrote called setCurrentDisplay() which is a wrapper for Display.getDisplay(this).setCurrent(newdisplay). My setCurrentDisplay method calls the showNotify and hideNotify methods manually when "switching" between different instances of UICanvas.
Believe it or not, this all worked like a charm. I no longer run out of memory.
So, I have a comment/warning for developers, and I have a question for Nokia.
NOKIA PLEASE ANSWER THIS!
My comment: Always use a very small number of instances of any object that extends FullCanvas. We were all taught to create a class that extends Canvas or FullCanvas, and just create multiple instances of this class for multiple interface Displayables. While this works fine on non-Nokia phones, it WILL NOT WORK on the 3650/7650 (maybe not even on other Nokia phones). Instead, you will need to create one or at most two instances of any object that extends FullCanvas, and you will need to write your interface code such that different interfaces draw to these same one or two FullCanvas objects. It is really best to use just one FullCanvas, that way you can use double buffering to avoid the screen switch flicker that occurs.
Now for my question, which I already partially posed. Nokia: Does your Canvas and FullCanvas implementation allocate a big chunk of memory for the display? Is this why my app kept running out of memory when I allocate multiple objects that extend FullCanvas? I kept checking the free memory and total memory, and I kept running out even when these said that the total memory was only 464KB. This is at least 1MB less than I thought the phone had, so of course I was surprised. But If Canvas and FullCanvas need to allocate their own big display buffers, and if this memory does not show up in the runtime.totalMemory() command, then I would expect to see exactly the behavior I did see. Anyway, why would Nokia use this approach? As I said, this same app works fine on phones with much less memory!
So Nokia what's the story here? PLEASE ANSWER!
Good luck to all
-------------------------------------------------------------------------------
Here's my FullCanvasImpl class:
public class FullCanvasImpl extends FullCanvas {
UICanvas currUI;
public FullCanvasImpl()
{
currUI=null;
}
public void paint(Graphics g) {
System.out.println("In FullCanvasImpl.paint for id = "+currUI.id);
if (currUI!=null) currUI.paint(g);
}
protected void keyPressed(int keyCode)
{
if (currUI!=null) currUI.keyPressed(keyCode);
}
}

Reply With Quote

