Blackberry Thread Exception - blackberry

how to kill a thread in blackberry.
I am using below code in which i want to kill a thread when dialog popup.
On first time login failed it is working properly but on second time login failed it returns RunTimeException.
public void onAuthFailed(String message) {
//this.invokeAndWait(new NotifyDialog("Please enter correct username and password"));
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
Dialog.alert("Please enter correct username and password.");
UiApplication.getUiApplication().pushScreen(loginscreen);
}
});
}

Code you posted is not dedicated to kill a thread. It will display a new screen. And I thing you are trying to display a screen object, that is already displayed. I. e loginscreen instance is already displayed. If loginscreen is not displayed, then there's confict (event lock) between new dialog box and screen to be displayed. Display dialog box and screen in different threads.
Check this tutorial: http://www.javabeginner.com/learn-java/java-threads-tutorial
I think it will help.

Related

Navigator push same screen multiple times

I need push new screen automatic on app startup (if user is login or sign out).
I am use scoped_model for auth so need navigate when user value is change in model.
I am follow Brian Egan suggestion here: https://github.com/brianegan/scoped_model/issues/43#issuecomment-442444143
class LoginScreenState extends State<LoginScreen> {
#override
void didChangeDependencies() {
ScopedModel.of<AuthModel>(context).addListener(_navigationListener);
super.didChangeDependencies();
}
#override
void dispose() {
ScopedModel.of<AuthModel>(context)
.removeListener(_navigationListener);
super.dispose();
}
void _navigationListener() {
switch (ScopedModel.of<AuthModel>(context).AuthStatus) {
case AuthStatus.NotAuth:
Navigator.of(context).pushNamed(‘/Login’);
break;
case AuthStatus.Auth:
Navigator.of(context).pushNamed(‘/Main’);
break;
case AuthStatus.Register:
Navigator.of(context).pushNamed(‘/Register’);
break;
}
AuthStatus is Enum. I change value in Model.
This is push route correct, but have issue:
Same route is push many times. For example, same Login page is push at least 5 times.
How to stop Navigator from push same screen multiple times?
Thanks!
In Brian Egan's example he had a boolean test in the _navigationListener method. His comment was:
// This function will be run every time the model changes! We will use it to
// check the navigate boolean. If it's set to true, we'll push a new screen!
//
// If not, we won't do anything.
So, a similar boolean needs to be used in your code to only navigate once despite how many times the method is called.

BlackBerry JDE 5 Application Slowing Down

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.
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.

RegisterForRemoteNotificationTypes causes UI to hang

I can successfully register my app for push notifications:
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(
UIRemoteNotificationType.Alert
| UIRemoteNotificationType.Badge
| UIRemoteNotificationType.Sound);
But whenever I execute this, my UI hangs for usually 2-3 seconds. Even if I have it early in the app lifecycle as recommended (e.g., even WillFinishLaunching) my UI still hangs once my first ViewController loads.
My first thought was to execute the registration in a separate thread, but MonoTouch prevents this:
// From MonoTouch.UIKit
public virtual void RegisterForRemoteNotificationTypes(UIRemoteNotificationType types)
{
UIApplication.EnsureUIThread();
My next thought was to at least pop up a UIAlertView box to let the user know something's going on, but for some reason it didn't display until after the registration took place, resulting in the UIAlertView opening and immediately closing!
modalPopup = new UIAlertView("Working", "The application is loading...", null, null);
modalPopup.Show();
// It doesn't show here!
RegisterForRemoteNotificationTypes();
// It shows here!
modalPopup.DismissWithClickedButtonIndex(0, true);
How can I either
Stop the push notification registration from tying up my UI thread
cover up the UI freeze?
Did you override public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
or
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
I've had similar problem where within Registered... function, I called a web service to upload the device token. But the web call wasn't within another thread so it caused to freezes UI.

Blackberry simple progressbar for BrowserField2

In my app I have a BrowserField2 loading different pages and I want to show a simple spinning progressbar/indicator. As simple as possible really, without percent etc. - just a small animation to indicate to the user that something is happening.
I come from Android development and there such a thing is called Progressbar, though for Blackberry it maybe is called something completely different? (Progressbar for Blackberry seems to always include calculating the progress made).
What should I be looking for?
I solved it in a rather unorthodox way, something I probably wouldn't recommend ANYONE but I'll write it anyway since maybe it will help someone who's in a hurry to get it done. Just remember this is a bad way of doing it.
My app basically consists of 4 buttons and a browserfield.
To display a spinning "load animation" I use alishaik786's tip (see his comments) of the custom PopupScreen triggered by a browserfieldlistener:
// BrowserFieldListener to catch when a page started loading and when it is finished
BrowserFieldListener listener = new BrowserFieldListener() {
public void documentCreated(BrowserField browserField, ScriptEngine scriptEngine, Document document) throws Exception{
displayLoadAnimation();
// see method below
}
public void documentLoaded(BrowserField browserField, Document document) throws Exception{
try{
popUp.close();
}catch(IllegalStateException es){
es.printStackTrace();
}
}
};
// The method for showing the popup
private void displayLoadAnimation(){
popUp = new LoadingPopupScreen();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(popUp);
}
});
}
Then in my custom PopupScreen I check where the user is clicking in "protected boolean touchEvent(TouchEvent event)" by checking event.getGlobalY() & event.getGlobalX() of the touch and comparing it to the positions of the buttons. If the user presses within the X&Y of a button then the popup screen is closed and I trigger the button being pressed.
As I said this is a bad way of doing it (many things need to be static), but it works if you want a quick and dirty sollution.

Delete a row from VerticalFieldManager

I am trying to establish a PIM listener that will update a MainScreen where all the contacts of the phone are listed.
What I am doing is the following:
I am loading for one time only a form called ContactsForm and I am storing it into the RuntimeStore
I created a PIMListListener to listen for all the changes that will occur in the address book.
When a contact is added, I am adding it to the contactsForm successfully
When a contact is removed, I am facing a big problem deleting it :S!!!
I am getting this exeption: "IllegalArgumentException"; this exception's text is : UiEngine accessed without holding the event lock. I know such errors and I know how to resolve them. So I used the following code:
UiApplication.getUiApplication().invokeLater( new Runnable() { public void run() {
synchronized(UiApplication.getEventLock()) {
uiContacts.vm.delete(uiContacts.vm.getField(j));
}
}});
This should resolve the problem. But I keep getting this error again and again. How to resolve this?
Listeners, like the PIMListListener, do not receive their callbacks in the same Application context as your UiApplication. So, in your code, UiApplication.getUiApplication() doesn't really work the way you'd expect it to.
The best thing to do would be to store a reference to your UiApplication in a place where the callback can reach it (during initialization of the UiApplication, perhaps), and then replace UiApplication.getUiApplication().invokeLater(...) with myUiApp.invokeLater(...), where myUiApp is the reference to your UiApplication which you stored earlier.

Resources