I am working with 2 resolutions one touchScreen and other Non- touch
i have designed a Screen which has 10 custombuttons are added to a VerticalFieldManager
The CustomButtonField class extends Field class
i have used 2 methods fieldChange() and touchEvent() for touchScreens
the problem is whenever i do click on button it gets activated correctly for touchevent()
but then the fieldChange() method also gets called immediately afterwards
what should i do??
what's the problem ??
Check the answers of the question BlackBerry touchEvent outside Field triggers fieldChanged provided by Paul Sylliboy and Arhimed.
In those answers, there was a method which only updates a boolean variable to identify that a touch event occured, and based on the value of that boolean an action is executed on the fieldChanged or navigationClick method.
BB UI Framework calls navigationClick(int status, int time)
automatically if there is any touch event after execution of
protected boolean touchEvent(TouchEvent message). And
navigationClick(int status, int time) calls the method
fieldChangeNotify(0) which causes fieldChange() (in the question)
or public void fieldChanged(Field field, int context) to be called.
Related
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.
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.
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.
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.
Is there an exit routine that will be called by the runtime every time a blackberry app signals that it wants to exit, similar to MIDlet.destroyApp(boolean) for traditional midlets?
If none exists, how do you ensure for instance that a particular task gets executed just before a blackberry app exits?
I think you are looking for onClose() method
public class MyMainScreen extends MainScreen {
public MyMainScreen() {
super();
}
public boolean onClose() {
// Your code here
}
}
public boolean onClose()
Indicates a close event has occurred.
The default implementation is
activated by specifying DEFAULT_CLOSE.
It will call onSavePrompt if the
screen is dirty, then call close() if
sucessful.