OK, this one is getting frustrating. I've reviewed the posts here regarding progressdialog bars in AsyncTasks and in regular threads, and nothing is working how I want it to.
In the AsyncTask I've done it this way:
#Override
protected void onPreExecute()
{
super.onPreExecute();
// initialize the dialog
progressDialog.setTitle("Please wait...");
progressDialog.setMessage("Downloading team data...");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected Boolean doInBackground(String... parms) {
... stuff
#Override protected void onPostExecute(Boolean result) {
progressDialog.dismiss();
}
When I do the above I get nothing until the doInBackground job finishes. The notes I've read say that using the get() method in the main is blocking the progressbar.
OK. I have to wait for the task to finish anyway before I can continue, so I wrote the same thing without an AsyncTask:
public class LoadTeamData2 {
Context mContext;
String teamName = "";
Boolean result;
String dataload = "";
ProgressDialog progressDialog;
public LoadTeamData2(Context mContext, String team) {
this.mContext = mContext;
teamName = team;
}
public Boolean LoadData () {
ProgressDialog progressDialog = new ProgressDialog(mContext);
progressDialog.setTitle("Please wait...");
progressDialog.setMessage("Downloading team data...");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
// progressDialog.show();
ProgressDialog.show(mContext, "Title", "Message", true, true);
... more stuff
progressDialog.dismiss();
return true;
}
From the above I get the briefest flash of the progressdialog bar.
I've even taken the progressdialog bar out of the called procedures and put the show() and dismiss() methods on both sides of the call to DoStuff. Still nothing.
At my wit's end here. Any ideas? Thanks!
You can start the ProgressDialog before you start executing the AsyncTask, for example:
gpsProgress = ProgressDialog.show(this, "Searching...", "Getting...", true, true, new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
}
});
(new SampleAsyncTask(this)).execute(param..);
and onPostExecute(Result) you may dismiss the dialog.
Please note, that the DialogBox show isn't in preExecute(), but in the activity which starts the AsyncTask.
The invoke asyncTask.get(XX,XX) blocks the UIThread,
My solution is put the UIlogic in onPostExecute() method, remove asyncTask.get(XX,XX)
Related
I've an combo box which is composed of a text field and a popup with a CellTable showing the suggestion items. The text field has a change handler that updates the CellTable's selection.
When typing a character and clicking an already selected suggestion, the first click is swallowed. The second click works and triggers the selection via the CellTable.addDomHandler(...).
Any idea why first click is swallowed?
Example code:
private static class SuggestFieldTextAndPopupSandbox extends SimplePanel {
private final TextField mText;
private CellTable<Handle<String>> mTable;
private SingleSelectionModel<Handle<String>> mTableSelection;
private SingleSelectionModel<Handle<String>> mSelection;
private ProvidesKey<Handle<String>> mKeyProvider = new SimpleKeyProvider<Handle<String>>();
private PopupPanel mPopup;
private List<Handle<String>> mData;
public SuggestFieldTextAndPopupSandbox() {
mData = Lists.newArrayList(new Handle<String>("AAA"), new Handle<String>("AAB"), new Handle<String>("ABB"));
mSelection = new SingleSelectionModel<Handle<String>>();
mText = new TextField();
mText.addKeyPressHandler(new KeyPressHandler() {
#Override
public void onKeyPress(KeyPressEvent pEvent) {
mPopup.showRelativeTo(mText);
}
});
mText.addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent pEvent) {
mTableSelection.setSelected(startsWith(mText.getValue()), true);
}
});
mText.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent pEvent) {
mText.setText(mText.getText().toUpperCase());
}
});
mTable = new CellTable<Handle<String>>(0, GWT.<TableResources>create(TableResources.class));
mTable.setTableLayoutFixed(false);
mTableSelection = new SingleSelectionModel<Handle<String>>(mKeyProvider);
mTable.setSelectionModel(mTableSelection);
mTable.addDomHandler(new ClickHandler() {
#Override
public void onClick(final ClickEvent pEvent) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
}, ClickEvent.getType());
mTable.addColumn(new TextColumn<Handle<String>>() {
#Override
public String getValue(Handle<String> pObject) {
return pObject.get();
}
});
mTable.setRowData(mData);
mPopup = new PopupPanel();
mPopup.setAutoHideEnabled(true);
mPopup.setWidget(mTable);
mPopup.setWidth("200px");
mPopup.setHeight("200px");
VerticalPanel p = new VerticalPanel();
p.add(mText);
setWidget(p);
}
private Handle<String> startsWith(final String pValue) {
final String val = nullToEmpty(pValue).toLowerCase();
int i = 0;
for (Handle<String> item : mData) {
String value = item.get();
if (value != null && value.toLowerCase().startsWith(val)) {
return item;
}
i++;
}
return null;
}
}
I reproduced your issue and here is the problem:
when you click on the suggestions the following is happening:
The text field is loosing focus which causes the corresponding ChangeEvent to be dealt with followed by the BlurEvent.
The click causes the popup to get the focus now which is why it is swallowed.
If you remove the ChangeHandler and the BlurHandler of the text field the issue disappears. But I think I found another solution
Try replacing the DOM handler of the mTable with a selection handler relative to the mTableSelection as follows:
mTableSelection.addSelectionChangeHandler(new Handler(){
#Override
public void onSelectionChange(SelectionChangeEvent event) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
});
Found a way how to properly solve this.
Skipping the blur handler when user hovers the suggestion list area seemed to fix that issue, at least from the tests that were done didn't see any more issues.
This was necessary because just before the user clicks a suggestion item, the text is blurred and it fires a selection change. This in turn cancels the selection made when user clicks an item.
I get the fact that it might take more than 10 lines of code (hopefully not more than 50), but I was wondering if you could help me anyway.
I'm trying to update one user's UI thread at runtime, based on another user's input. I've created a basic project which implements three predefined users (jim, tom and threeskin). I'd like to send a message from jim to tom and have it appear as a new Label object in tom's UI, without threeskin ever knowing about it, even though they're all logged in. Oh, and jim shouldn't have to refresh his page. The label should just spawn on screen out of it's own accord.
To say that I'd appreciate some help would be the understatement of the decade.
public class User {
public String nume;
public User(String nume) {
super();
this.nume = nume;
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class Engine implements ServletContextListener {
public static ArrayList<User>userbase;
public void contextDestroyed(ServletContextEvent arg0) { }
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("This code is running at startup");
userbase =new ArrayList<User>();
userbase.add(new User("jim"));userbase.add(new User("tom"));userbase.add(new User("threeskin"));
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class InfigeUI extends UI {
User us3r;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = InfigeUI.class)
public static class Servlet extends VaadinServlet {}
protected void init(VaadinRequest request) {
VerticalLayout everything=new VerticalLayout();
setContent(everything);
if (us3r==null){everything.addComponent(auth());}else{everything.addComponent(main());}
}
ComponentContainer auth(){
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
TextField userField=new TextField();
Button login = new Button("Log in");
login.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
us3r=login(userField.getValue());
if (us3r!=null){
saveValue(InfigeUI.this, us3r);
layout.removeAllComponents();
layout.addComponent(main());
}else{Notification.show("I only know jim, tom and threeskin. Which one are you?");}}
});
layout.addComponent(userField);
layout.addComponent(login);
return layout;
}
User login(String nume){
for (int i=0;i<Engine.userbase.size();i++){
if (nume.equals(Engine.userbase.get(i).nume)){return Engine.userbase.get(i);}
}
return null;
}
static void saveValue(InfigeUI ui,User value){
ui.us3r=value;
ui.getSession().setAttribute("something", value);
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("something", value);
}
ComponentContainer main(){
VerticalLayout vl=new VerticalLayout();
Label label=new Label("This is the post-login screen");
String name=new String(us3r.nume);
Label eticheta=new Label(name);
TextField to=new TextField("Send to");
TextField message=new TextField("Message");
Button sendNow=new Button("Send now!");
vl.addComponent(eticheta);
vl.addComponent(label);
vl.addComponent(eticheta);
vl.addComponent(to);
vl.addComponent(message);
vl.addComponent(sendNow);
return vl ;
}
}
Basically you want three things
UI updates for a user which does no action himself, or in other words a message sent from the server to the browser. To enable this, you need to annotate the UI class using #Push. Otherwise, the update will only be shown when the user does something which causes a server visit, e.g. clicks a button
Some way of sending messages between UI instances (there is one UI instance per user). You can use some message bus implementation for this (CDI, Spring, ...) or you can make a simple on using a static field (static fields are shared between all users). See e.g. https://github.com/Artur-/SimpleChat for one way of doing it. It's also a good idea here to avoid all *.getCurrent methods as they in many cases will refer to another UI than you think (e.g. sender when you are in the receiver code), and you will do something else than you intend.
Safely update a UI when a message arrives. This is done using UI.access, also visible in the chat example.
First of all you need to enable the server push on your project help
based on Vaadin Documentation.
However, below code example will give what you want:
Create an Broadcast Listener Interface:
public interface BroadcastListener {
public void receiveBroadcast(final String message);
}
The Broadcaster Class:
public class Broadcaster {
private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>();
public static void register(BroadcastListener listener) {
listeners.add(listener);
}
public static void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static void broadcast(final String message) {
for (BroadcastListener listener : listeners) {
listener.receiveBroadcast(message);
}
}
}
Your UI with Push Enalbed (via Annotation):
#Push
public class BroadcasterUI extends UI implements BroadcastListener {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
final TextArea message = new TextArea("",
"The system is going down for maintenance in 10 minutes");
layout.addComponent(message);
final Button button = new Button("Broadcast");
layout.addComponent(button);
button.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Broadcaster.broadcast(message.getValue());
}
});
// Register broadcast listener
Broadcaster.register(this);
}
#Override
public void detach() {
Broadcaster.unregister(this);
super.detach();
}
#Override
public void receiveBroadcast(final String message) {
access(new Runnable() {
#Override
public void run() {
Notification n = new Notification("Message received",
message, Type.TRAY_NOTIFICATION);
n.show(getPage());
}
});
}
you can find the full link here.
I have in my ViewSwitcher a ListView and a WebView. In my ListView's adapter, I have an onclick listener that writes the clicked url in the list to sharedpreferences. I'm trying to load that url into the WebView using an onSharedPreferencesChangedListener.
This is the code in my adapter:
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewSwitcher.showNext();
Settings.writeSettings(context, "webviewUrl",
urls.get(position));
}
});
return convertView;
And in the preference listener:
#Override
public void onSharedPreferenceChanged(SharedPreferences pref, String key) {
if (key.equals("webviewUrl")) {
Log.d("TAG", pref.getString(key, null));
WebView wv = (WebView) findViewById(R.id.rss_webview);
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebViewClient(new MyWebViewClient());
wv.loadUrl("about:blank");
wv.loadUrl(pref.getString(key, null));
}
}
This works great except it only works once. The preference listener code logs the correct urls, and the code executes each time I want it to, but wv.loadUrl() method seems to do nothing after the first successful call. Can anyone explain to me why this is happening and perhaps offer a solution? Thanks.
I solved the problem by implementing a static ViewHolder on the WebView whose reference I needed to keep longer than its views' lifecycle.
private static final class WebViewHolder {
WebView wv;
}
#Override
public void onSharedPreferenceChanged(SharedPreferences pref, String key) {
WebViewHolder holder = new WebViewHolder();
if (key.equals("webviewUrl")) {
if (wv == null) {
wv = new WebView(this);
holder.wv = (WebView) findViewById(R.id.rss_webview);
holder.wv.getSettings().setJavaScriptEnabled(true);
holder.wv.setWebViewClient(new MyWebViewClient());
wv.setTag(holder);
} else {
holder = (WebViewHolder) wv.getTag();
}
holder.wv.loadUrl("about:blank");
holder.wv.loadUrl(pref.getString(key, null));
}
}
i need to update a textView from my asynctask. I have an custom adapter for the listview and there i want to have a countdown for each entry. I will start the asynctask for each entry from my Adapter. How can i update the textview each second from the asynctask?
Thanks for help :)
If you post your code, I can give you a better answer. However, a common way to update views periodically is by using Handlers.
private final Handler mHandler = new Handler(); //intialize in main thread
public void test() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mTextView.setText("hello");
}
}, 1000);
}
You can do something like this (this will add an entry to a list view every one second). I have used the normal ArrayAdapter to add a string. You can use your custom adapter to do something similar. The publishProgress() method basically triggers the onProgressUpdate() method which hooks to the UI thread and displays the elements getting added.:
class AddStringTask extends AsyncTask {
#Override
protected Void doInBackground(Void... params) {
for(String item : items) {
publishProgress(item);
SystemClock.sleep(1000);
}
return null;
}
#Override
protected void onProgressUpdate(String... item) {
adapter.add(item[0]);
}
#Override
protected void onPostExecute(Void unused) {
Toast.makeText(getActivity(), "Done adding string item", Toast.LENGTH_SHORT).show();
}
}
I am using gwt 2.3 with gwtp framework.In this application I wan to maintain a session time of 5 mins.This means if current user is not doing up to 5 min and he comes after five min then on his first event/action on screen a he should be be logged out.
In gwt there is class named Timer which can be used in this issues.But I am not getting how to recognize action of user on the screen.I did google on it, & found the code for gwt-ext.Below is the code of gwt-ext
Ext.get(“pagePanel”).addListener(“click”, new EventCallback() {
#Override
public void execute(EventObject e) {
MessageBox.alert(“On Mouse Click”);
}
});
Ext.get(“pagePanel”).addListener(“keydown”, new EventCallback() {
#Override
public void execute(EventObject e) {
MessageBox.alert(“On Key Press Click”);
}
});
In above code tag in working properly so I am attaching link from where I got this code.here
Same type of code I am looking in gwt.If there any other better way to do this then please let me know. Thanks in advance
If action/event can be really everythin, I would solve it with a
NativePreviewHandler in the following way:
boolean expired;
final Timer logoutTimer = new Timer() {
#Override
public void run() {
expired = true;
}
};
NativePreviewHandler nph = new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (!expired) {
logoutTimer.cancel();
logoutTimer.schedule(300000);
} else {
// do your logout stuff here
}
}
};
Event.addNativePreviewHandler(nph);
If the user shell be logged out without a new action after 5 minutes:
final Timer logoutTimer = new Timer() {
#Override
public void run() {
// do your logout stuff here
}
};
NativePreviewHandler nph = new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
// Of course do this only when logged in:
logoutTimer.cancel();
logoutTimer.schedule(300000);
}
};
Event.addNativePreviewHandler(nph);