I have a class on which I have a map object. I send this map object to a custom Dialog. After that I want to call another dialog from this dialog, but the second dialog is not showing. I don't know where i m doing wrong.
Activity :
dlgi = new MyCommunityServicesDialog(AppCentral.this, myValues, mapView);
dlgi.listDialog().show();
Custom Dialog :
Community_List_Dialog dialog = new Community_List_Dialog(context, getAllCommunityNames(selectedOpt).get(0), getAllCommunityNames(selectedOpt).get(1), mapView)
dialog.showDialog();
NOTE : This method (getAllCommunityNames(selectedOpt).get(0)/(1)) returns String[].
Custom Dialog Second :
public Dialog showDialog()
{
Log.i("listDialog calling...", "calling...");
final Dialog community_dialog = new Dialog(context);
community_dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
community_dialog.setContentView(R.layout.community_list);
ListView community_list = (ListView)community_dialog.findViewById(R.id.community_list);
adapter = new Community_List_Adapter(context,names);
community_list.setAdapter(adapter);
return community_dialog;
}
The solution to this problem was making use of the class
android.os.AsyncTask<Params, Progress, Result>
Description is given in die JavaDoc:
"AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers."
By using the methods onPreExecute() you can manipulate View on the UI Thread.
After finishing this method, doInBackground() is invoked and here you can start your background operations. This method is not working on the UI Thread, so it is not blocking your application.
After this onPostExecute() is invoked and you can use your computeted results.
My problem was to correctly show a progress indicator while the background oeprations are made. This can be done by making use of the onProgressUpdate() method, which is working ob the UI Thread, while the background computations are made.
Related
I have a created non activity java class for doing same calculation from different activities. This class has asynctask with progress Dialog in it. In most cases calculation is not the last operation of activity and everything goes fine, but when it is my Progress Dialog goes lost.
Example:
myJavaClass doCalculations= new myJavaClass (SomeActivity.this);
doCalculations.Do(); //<------ method Do has asysctask with Progress Dialog
finish();
result:
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{2bbf820e V.E..... R......D 0,0-1026,483} not attached to window manager
How can I wait for asynctask to finish and then finish activity?
Additional question: Is using asynctask in non activity class is a bad practice ?
If you want to keep your activity active until the AsyncTask has finished its job, you can define a callback method in the activity that gets called when the task has finished and can react appropriately:
In the Activity:
private boolean finishAfterCurrentTask = false;
public void onTaskFinished() {
if (finishAfterCurrentTask) { // set this to true when running the last task
finish();
}
}
In the AsyncTask:
protected void onPostExecute(Object result) {
progressDialog.dismiss();
activity.onTaskFinished();
}
I'm assuming that you're keeping a reference to the activity in myJavaClass. In case that you're calling the AsyncTask from a non-UI thread, you should probably run the callback (and also all methods involving the dialog) via Activity.runOnUiThread().
As for the second question - if you use an AsyncTask in a class which methods can be called from a thread other than the UI thread, it's necessary to use runOnUiThread() to perform any operations on the UI, such as changing the contents of a view or showing/hiding a dialog, beause onPreExecute() and onPostExecute() are called from the same thread as execute().
On the other hand, if you start the task inside one of the UI callbacks, which are guaranteed to run on the UI thread, you don't need to worry about that.
The AsyncTask has a onPostExecute method you can finish the activity from there
protected void onPostExecute(Long result) {
progressDialog.dismiss();
finish(); // you'll probably have to call finish() with a callback function
}
The onPostExecute method is called when the doInBackground method is finished, on that method you can finish the activity and close the progressdialog
How to block UI thread from doing anything and just displaying a progress bar until certain condition is met.
For example I have a list initialized to null, Lets call it list. I start another thread in UI to initialize its value which is going to take around 10 seconds. How can I block UI thread displaying progress dialog until the list is initialized.
// Initially
List list = null;
// Display progress bar until certain condition is met
while(list == null){
// Display progress dialog
}
I think AsyncTask will work if we ask that AsyncTask to update the list etc, what about another thread doing it. I have tried to simplify the problem.
you need to create a public method in mainActivity, named for examble yourcallback()
instead of instantiating all the objects in the OnCreate mainActivity, you can instantiate all objects in addition to quell ic you need for the progressbar in the callback method
yourcallback()
your callback
now you need to create an extenction of AsyncTask where you declare a base method constructor
like this
privte Activity mainObj;
public TestAsyncTask(Context context, Activity mainact ) throws Exception {
mainObj=mainact
your code
}
when the task naturally terminate the class AsyncTask call onPostExecute method
protected void onPostExecute(Long result) {
mainObj.yourcallback();
}
hope this help!
I am trying to update my list and display the updated list in my activity. Every time I do so I get the following error
The content of the adapter has changed but ListView did not receive a notification.
Make sure the content of your adapter is not modified from a background thread,
but only from the UI thread.
Here is my code, I am using an AsyncTask to achieve this task. I call notifyDataSetChanged() on my adapter but it does not seem to work. What am I doing wrong?
class MyTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
GregorianCalendar currentDateclone = (GregorianCalendar) currentDate.clone();
ListPopulater2.listPopulate(currentDateclone, 7, items, Id);
//method to update list info
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
progressdialog = ProgressDialog.show(SectionListExampleActivity.this, "", "Loading..."); //display progress bar
super.onPreExecute();
}
// -- called as soon as doInBackground method completes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.d("postExecute", "here");
adapter.notifyDataSetChanged();
progressdialog.cancel();
}
}
Try moving:
ListPopulater2.listPopulate(currentDateclone, 7, items, Id);
to your onPostExecute.
The reason that this worked is because you need to update the list after you've completed all your background activity, not while you are doing it. You can use the onProgressUpdate, but that is for your progress dialog. Updating you list view should be done after you have all you data, otherwise, you will get the error you did because the UI runs on the main thread, and you are trying to update it with the background thread.
As for the progress dialog, there is a purpose. If you are doing something that is going to take awhile to complete, the dialog will tell the user how close you are to completing the background task.
Hope that makes sense.
When Ever you want to do something which deal with the UI you have to do that task in UI thread.
So for this you can use 2 approach:
use runOnUi() method
Use OnPostExecute() method
And you have to use notifyDatasetchanged() at that place where you are setting adapter in listView.
I first show a progressDialog and then kick off a Thread from my Activity to get a url. I pass a handler also from Activity to the Thread's request listener, and then when the Thread is complete, control is passed to a requestListener, in the requestListener, I call an asynctask to get another URL, finally when this is complete, I call the handler to show a success Dialog on the original Activity.
The success dialog shows fine, which means that the handler really is running on the UI thread, but I cannot get a reference back to the progressDialog.
I've tried : passing the pDialog to the Handler, referring to it from a global application state, setting it as a static member of Activity.
But the progress dialog is always null....what is going on??? Why can I show the success dialog from the Handler, but not get a handle to the progressDialog
I have solved this issue...
I had:
public void showProg() {
pDialog = new ProgressDialog(this);
pDialog.setMessage(getString(R.string.loading));
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.show();
}
and when I move the contents of this method outside to the same place I was calling it...every works.....what is up???
I want to update my UI from a Thread which updates a Progressbar. Unfortunately, when updating the progressbar's drawable from the "runnable" the progressbar disappears!
Changing the progressbars's drawable in onCreate() on the otherside works!
Any Suggestions?
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
handler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
//* The Complete ProgressBar does not appear**/
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
}
});
}
}
You should do this with the help of AsyncTask (an intelligent backround thread) and ProgressDialog
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Threading rules
There are a few threading rules that must be followed for this class to work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Example code
What the adapter does in this example is not important, more important to understand that you need to use AsyncTask to display a dialog for the progress.
private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(viewContacts.this);
dialog.setMessage(getString(R.string.please_wait_while_loading));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
/* (non-Javadoc)
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected ContactsListCursorAdapter doInBackground(Void... params) {
cur1 = objItem.getContacts();
startManagingCursor(cur1);
adapter1 = new ContactsListCursorAdapter (viewContacts.this,
R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});
return adapter1;
}
protected void onPostExecute(ContactsListCursorAdapter result) {
list.setAdapter(result);
dialog.dismiss();
}
}
The most simplest solution I have seen to supply a short
execution to the UI thread is via the post() method of a view.
This is needed since UI methods are not re-entrant. The
method for this is:
package android.view;
public class View;
public boolean post(Runnable action);
The post() method corresponds to the SwingUtilities.invokeLater().
Unfortunately I didn't find something simple that corresponds to
the SwingUtilities.invokeAndWait(), but one can build the later
based on the former with a monitor and a flag.
So what you save by this is creating a handler. You simply need
to find your view and then post on it. You can find your view via
findViewById() if you tend to work with id-ed resources. The resulting
code is very simple:
/* inside your non-UI thread */
view.post(new Runnable() {
public void run() {
/* the desired UI update */
}
});
}
Note: Compared to SwingUtilities.invokeLater() the method
View.post() does return a boolean, indicating whether the
view has an associated event queue. Since I used the
invokeLater() resp. post() anyway only for fire and forget,
I did not check the result value. Basically you should
call post() only after onAttachedToWindow() has been called
on the view.
Best Regards
If you use Handler (I see you do and hopefully you created its instance on the UI thread), then don't use runOnUiThread() inside of your runnable. runOnUiThread() is used when you do smth from a non-UI thread, however Handler will already execute your runnable on UI thread.
Try to do smth like this:
private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
res = getResources();
// pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
mHandler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
pB.invalidate(); // maybe this will even not needed - try to comment out
}
};
Use the AsyncTask class (instead of Runnable). It has a method called onProgressUpdate which can affect the UI (it's invoked in the UI thread).
You need to create a Handler in the UI thread and then use it to post or send a message from your other thread to update the UI
If you don't like the AsyncTask you could use the observer pattern. In that example use the ResponseHandler as an inner class in your activity then have a string message that will set the progress bars percentage... You would need to make sure that any alterations to the UI are performed within the ResponseHandler to avoid freezing up the UI, then your worker thread (EventSource in the example) can perform the tasks required.
I would use the AsyncTask tho, however the observer pattern can be good for customization reasons, plus its easier to understand. Also im not sure if this way is widely accepted or will 100% work. Im downloading and the android plugin now to test it
As recommended by official documentation, you can use AsyncTask to handle work items shorter than 5ms in duration. If your task take more time, lookout for other alternatives.
HandlerThread is one alternative to Thread or AsyncTask. If you need to update UI from HandlerThread, post a message on UI Thread Looper and UI Thread Handler can handle UI updates.
Example code:
Android: Toast in a thread