1

I'm fairly new to writing BlackBerry applications, so maybe this is a stupid thing I'm overlooking. I have to use JDE 5 (client requirement) to support the older BlackBerry Curve 8520 phones.

What I am experiencing is that as soon as I place a DateField on my interface, the application slows down considerably, causing the UI to stutter. Even a simple layout that only has a single DateField and a button has the same effect. Then, as soon as I move on to the next layout, everything is fine again.

One of the layouts are created as follows (please comment if this is the incorrect way of doing it):

public void displaySomeLayout() {
    final ButtonField okButton = new ButtonField("OK");
    final DateField dobField = new DateField("Birthday", System.currentTimeMillis(), DateField.DATE);

    /* some other non-ui code */

    UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
            applicationFieldManager.addAll(new Field[] {
                    dobField,
                    okButton
            });
        }
    });
}

The application then just slows down a lot. Sometimes, after a minute of so it starts responding normally again, sometimes not.

The displaySomeLayout() method is called from the contructor of the Screen extending class. And then applicationFieldManager is a private VerticalFieldManager which is instantiated during class construction.

Michael Donohue
  • 11,776
  • 5
  • 31
  • 44
Nico Huysamen
  • 10,217
  • 9
  • 62
  • 88
  • **Where** are you putting the code you show above? Is it in the constructor for a `Screen` subclass, maybe? And what does `methodToGetObjectArray()` return? Does it return many, many objects, or just a few? – Nate Jul 01 '13 at 09:39
  • @Nate - It is not in the constructor. It is run when a specific method is called on that Screen (to update it's display). The `methodToGetObjectArray()` returns about 250 elements, but I have found that the phone handles it just fine. It's as soon as the `DateField` gets added that things go slow. – Nico Huysamen Jul 01 '13 at 10:23
  • That's different from what you said in your question. In the question, it says that adding the `ObjectChoiceField` **or** the `DateField` causes the problem. If the `ObjectChoiceField` is not the problem, please don't show us that code. Show us the code that **is** the problem, as you see it. Also, you still didn't really answer the question regarding **where** the code you show is run. Finally, 250 choices is actually a lot. That sounds like a UI that users will hate to scroll through. Is 250 really necessary? – Nate Jul 01 '13 at 10:55
  • @Nate Yes it is necessary unfortunately, they need to choose their country of residence. I will update my question wrt your other questions. – Nico Huysamen Jul 01 '13 at 12:16

1 Answers1

0

I'm not sure the problem is in the code that you've shown us. I think it's somewhere else.

However, here are a couple recommendations to improve the code you've shown:

Threading

First of all, the code you show essentially is being run in the Screen subclass constructor. There is almost no difference between this code:

public MyScreen() {
   Field f = new ButtonField("Hello", ButtonField.CONSUME_CLICK);
   add(f);
}

and this:

public MyScreen() {
   addField();
}

private void addField() {
   Field f = new ButtonField("Hello", ButtonField.CONSUME_CLICK);
   add(f);
}

So, because your code is being run in the screen class's constructor, it should already be running on the UI thread. Therefore, there's no reason to use UiApplication.getUiApplication().invokeLater() here. Instead, just use this:

public void displaySomeLayout() {
    final ButtonField okButton = new ButtonField("OK");
    final DateField dobField = new DateField("Birthday", System.currentTimeMillis(), DateField.DATE);

    /* some other non-ui code */

    applicationFieldManager.add(dobField);
    applicationFieldManager.add(okButton);
}

Sometimes, you do need to use invokeLater() to run UI code, even when you're already on the UI thread. For example, if your code is inside the Manager#sublayout() method, which runs on the UI thread, adding new fields directly will trigger sublayout() to be called recursively, until you get a stack overflow. Using invokeLater() can help there, by deferring the running of a block of code until sublayout() has completed. But, from the constructor of your screen class, you don't need to do that.

ObjectChoiceField

I'm also worried about the ObjectChoiceField you said you were using with 250 choices. You might try testing this field with only 10 or 20 choices, and see if that makes a difference.

But, even if the 250 choice ObjectChoiceField isn't the cause of your performance problems, I would still suggest a different UI.

On BlackBerry Java, you can use the AutoCompleteField. This field can be given all the country choices that you are now using. The user starts typing the first couple letters of a country, and quickly, the list narrows to just those which match. I personally think this is a better way to get through a very large list of choices.

Community
  • 1
  • 1
Nate
  • 31,017
  • 13
  • 83
  • 207
  • Thanks for the input. Just 2 things. It's a given that a method called from the constructor is 'basically' still in the constructor. The `displaySomeMethod()` is called after a certain event happens, not from the constructor, and that is why I am grabbing the UI thread. Then, the `ObjectChoiceField` does not seem to be my issue, just the `DateField`. I tried it on a screen with just the `DateField` and it still seems sluggish (JDE 5). Thanks for the heads-up on the `AutoCompleteField`, will definitely give it a go. – Nico Huysamen Jul 08 '13 at 07:46
  • @NicoHuysamen, I think I was responding to the update to your question that said *"The displaySomeLayout() method is called from the contructor of the Screen extending class."*. That's why I made the statement about the method running in the constructor. If that first statement wasn't what you meant to say, that's fine. However, with this *"certain event"* that you mention in your last comment, if that event runs on the UI thread, you still probably don't need the `invokeLater()` call. If the event callback isn't on the UI thread, then you do, of course. – Nate Jul 08 '13 at 08:34