continue ProgressDialog until onPostExecute finishes - android

I know that progress dialog will stop spinning if it's not terminated immediately inside onPostExecute(). However, I have some methods to call inside onPostExecute() and I cannot transfer them to doInBackground() because these methods should run on UI. Is there a possible way to continue the progressDialog after calling these methods without stopping it to spin?
Here is the onPostExecute of my AsyncTask:
protected String doInBackground(final String... strings) {
//Network activity here
}
protected void onPostExecute(String unused){
//progressdialog stops spinning here, cannot change the message also
try {
if(response.equals("HOST ERROR") || response.equals("CONNECTION ERROR") || response.equals("ERROR")){
new AlertDialog.Builder(context).setTitle("Error").setMessage("Cannot connect to the internet.").setNeutralButton("Close", null).setIcon(android.R.drawable.ic_delete).show();
}
else{
doc = Jsoup.parse(response);
Intent cc = new Intent(activity,com.sblive.aufschoolbliz.GradeBook.class);
subjectCodes = getSubjectCodes(); //this parsing method should run on UI
professors = getProfs(); //this parsing method should run on UI
grades = getGrades(); //this parsing method should run on UI
cc.putExtra("subjectCodes", subjectCodes);
cc.putExtra("professors", professors);
cc.putExtra("grades", grades);
if(this.pd.isShowing()) {
this.pd.dismiss();
}
context.startActivity(cc);
}
}
catch (NullPointerException e) {
}
}

<<< EDIT: >>>
Ok forget about what I posted, silly me. Of course anything that modifies user interface needs to be called/dismissed on the UI thread.
So what I would do is run everything possible during doInBackground(), and creating/dissmissing the dialog or anything that requires to be run on the UI thread explicitly like this:
this.runOnUiThread(new Runnable() {
public void run() {
/*Code required to run on UI thread*/ }
});
And im afraid that's as much as you can do without overdoing way too much.

Related

AsyncTask to call another function within class

Basically, do I have to put code I want to run on another thread inside doInBackground, or can I call another function/class/whatever-it-is-functions-are-called-in-JAVA within doInBackground and have it run asynchronously? IE: (example code I found online)
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}
is how I have seen it done, but can I instead do:
protected String doInBackground(String... params) {
postToServer(x,y,z,h);
}
and have it call a function I already wrote and then have that function run in another thread? Sometimes my HTTP server is a bit slow to respond (it is but a lowly testing server at the moment) and Android automatically pops up the kill process box if my postToServer() call takes more than 5 seconds, and also disables my UI until the postToServer() call finishes. This is a problem because I am developing a GPS tracking app (internally for the company I work for) and the UI option to shut the tracking off freezes until my postToServer() finishes, which sometimes doesn't ever happen. I apologize if this has been answered, I tried searching but haven't found any examples that work the way I'm hoping to make this work.
You can do that, but you will have to move the UI updates to onPostExecute as it is run on the UI thread.
public MyAsyncTask extends AsyncTask<foo, bar, baz> {
...
protected String doInBackground(String... params) {
postToServer(x,y,z,h);
}
protected void onPostExecute(Long result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
....
}
You may want to pass in the TextView to the constructor of the AsyncTask and store it as a WeakReference.
private final WeakReference textViewReference;
public MyAsyncTask(TextView txt) {
textViewReference = new WeakReference<TextView>(txt);
}
And then in onPostExecute you would make sure that the TextView reference still exists.
protected void onPostExecute(Long result) {
TextView txt = textViewReference.get();
if (txt != null)
txt.setText("Executed");
}
If you want to notify the user that the task is executing I would put that before invoking the AsyncTask.
myTextView.setText("Update in progress...");
new MyAsyncTask().execute();
then in onPostExecute set the TextView to say "Update complete."
Have you tried it the second way?
From what you've posted it seems like it should work fine how you have it in the second example.
However (perhaps unrelated to your question?) in your first example I think it will fail because you are trying to change the UI from a background thread. You'd want to put the parts that manipulate the TextView inside of onPostExecute() rather than doInBackground()
Yes you can, the call to your postToServer method (that's the name in java) will run off the main thread.
Everything inside the doInBackground method of an AsyncTask is run on a pooled thread, but be sure to NOT invoke it directly! Call execute on your asynktask instead, the android framework will do the work for you and run doInBackground on another thread.
try doing something like this:
new AsyncTask<Void, Void, Void>() {
#Override
// this runs on another thread
protected Void doInBackground(Void... params) {
// assuming x, y, z, h are visible here
postToServer(x, y, z, h);
return null;
}
#Override
// this runs on main thread
protected void onPostExecute(Void result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
}.execute(); // call execute, NOT doInBackGround
Also, notice that every other method of AsyncTask, such as onPostExecute runs on the main thread, so avoid heavy loading them.
Basically The Bottom Line Is the doInBackground() method is Can't interact with The Ui Thread Or The Main thread. that's Why When You are Try To Interact With The TextView in doInBackground () it Will Crash the UI Thread Cuz It's Illegal.
so if anytime You want to Interact with the UI Thread,When You are Working on doInBackground You need to Override
OnPostExecute() //this Function is Called when The doInBackground Function job is Done.
So You can Update The UI Thread Content By this When You're Job is Done In doInBackground () or You are In doInBackground ()

How to work with AsyncTask and threads?

The goal:
Using Google App Engine server and Android client, I'm trying to put on the Google map at the Android client Users overlays. Every 30 seconds I'm polling the server and getting Vector that contains users and adding it to the map.
Current status:
I'm dong all that using in one new thread, So after running the app I got:
weird behaviors(delayed overlays, multiple overlays) and after that crushed with ConcurrentModificationException.
After reading a bit i figured out that I need to work with AsyncTask.
Correct me if I'm wrong,But I understand that everything done in the Activity at at onCreate is "running" in UIhread so I need to put the "Logic" (All the Network handling) in doInBackground and all the UI Handling like putting overlays on the map in onPostExecute.
My Question are:
1) In the current status I'm doing:
new Thread()
{
#Override
public void run()
{
super.run();
while(true)
{
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
putNewOnlineUserOnTheMap();
}
}
}.start();
What is the right way to convert this To AsyncTask?
Do I poll the server still using new thread in the doInBackground or there is right way to do this?
2) Is there a specific list of what counts as UI to put in onPostExecute or any concepts list?
In my case I guess that in need to put putNewOnlineUserOnTheMap() in onPostExecute.
Thanks.
Something similar to the following:
class UpdateTask extends AsyncTask<Void, Vector, Void>{
#Override
protected Void doInBackground(Void... params) {
// this is running in a background thread.
while (!isCancelled()) {
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
// send the result back to the UI thread
// onProgressUpdate will be called then
publishProgress(responseFromServer);
}
return null;
}
#Override
protected void onProgressUpdate(Vector... values) {
// this is executed on the UI thread where we can safely touch UI stuff
putNewOnlineUserOnTheMap(values[0]);
}
}
You can't use the result of the task since the task is finished then. But you can use the progress publishing mechanism to get periodic results. If you use it like that and do the modification on the UI thread you should not get ConcurrentModificationException because you do the modifications on the one thread that can safely modify the UI.
One thing to note here: create new instances of your Vector in the background thread and then use it to update the UI. But don't touch the same object afterwards in the backgroundthread. That way you don't need any synchronization since after the background thread sends it away it is only the UI thread that touches it. (and you could use a simple ArrayList instead of a Vector)
AsyncTask uses generics and varargs.The parameters that are passed to the asyntask are . TypeOfVariableArgumentsParameters is passed into the doInBackground(), ProgressParam is used for progress information and ResultParam must be returned from doInBackground() and is passed to onPostExecute() as parameter.
example:--
protected class ParsingTask extends AsyncTask> {
private ProgressDialog loadingDialog = new ProgressDialog(JsonParserActivity.this);
protected void onPreExecute() {
loadingDialog.setMessage("loading app store..");
loadingDialog.show();
}
#Override
protected ArrayList<Items> doInBackground( Context... params ) {
// do ur process here.
return result;
}
if (!this.isCancelled()) {
}
return result;
}
#Override
protected void onProgressUpdate(String... s) {
super.onProgressUpdate(s);
Toast.makeText(getApplicationContext(), s[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute( ArrayList<Items> response ) {
//if u r dealing with list view and adapters set the adapter here at the onPostExecute()
loadingDialog.dismiss();
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(getApplicationContext(), "The operation was cancelled", 1).show();
}
}
You can use AsyncTask like below. Hope this will help you..
Class YourClass{
void YourClass(){
NetworkTask nT = new NetworkTasK();
nT.execute();
}
}
protected class NetworkTask extends AsyncTask<Void, String, Boolean>
{
#Override
protected Boolean doInBackground(Void... params)
{
try
{
String response;
while(keepreceiving)
{
response = in.readLine();//Prog Counter stops here until getting i/p.
if(response != null)
yourFunctionForResponse(response);
}
}
catch (Exception ex)
{
}
return null;
}
private void yourFunctionForResponse(String response){
//things to do....
}
}
You may also try runOnUiThread(Runnable action) along with this to implement your work.

Asyntask: why update UI Thread in doInbackground will meet error?

when I read document about asyntask, they say that: "should not" update UI thread in doInbackground because doInbackground work on different thread.
that means : this action will dangerous because UI Thread isn't thread-safe. I understand it. but when I try for test what happen when I update UI Thread in this function. I receive error: (but error doesn't not look like because aysnchonize, but because we CANNOT do it)
(TextView)((Activity)context).findViewById(R.id.text)).setText("StackOverFlow");
//context: reference of context object of UI Thread
Please explain for me. Does we shouldn't or mustn't .
thanks :)
what I have understand so far with android is...,
we can't update UI thread from background thread.
May be it is the case they have stopped us to update UI from background thread.
The reason for that is very clear... # OS level there will be so many thread will be running.
And also
different thread from different application, And in that case It will be chaos on the screen, if we can update UI from bg-thread
Inside the doInBackgroundyou will not get the UI access. If You Want to take UI access publishProgress from doInBackgroundyou will go to the onProgressUpdate from there do what you wan to show on UI.
Below is the Code you will check for your reference :
class DownloadAsyncTask extends AsyncTask
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(Login.this, "", "Please Wait ...");
}
#Override
protected Void doInBackground(String... arg0) {
int status1 = validationuser(username);
Log.i("MyLog", "Inside the doInBackground is came"+status1);
if(status1 == 1)
{
publishProgress(status1+ "Valid User Code","1",""+status1);
}
else
{
publishProgress(status1+ " Invalid Valid User Code","0",""+status1);
}
return null;
}
#Override
protected void onProgressUpdate(String...values){
super.onProgressUpdate(values);
int index = Integer.parseInt(values[2]);
if(index == 1)
{
USERIDLOGIN = edittextuserName.getText().toString();
Intent intent=new Intent(Login.this, CollectionModuleandDownload.class);
/*Toast.makeText(Login.this, "Valid User Password", Toast.LENGTH_SHORT).show();*/
startActivity(intent);
progressDialog.dismiss();
}
else
{
Toast.makeText(Login.this, "Invalid Username & Password", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
/*if(progressDialog != null)
{
progressDialog.dismiss();
}*/
}
}
so you have to update ui only on the OnPostExecute & OnPreExecute.
here's a good example of asynctask. give it a try
you call it by
new SaveProfile().execute();
then this...
private class SaveProfile extends AsyncTask<String, Void, Boolean>{
#Override
protected Boolean doInBackground(String... params) {
//---------- so your stuff here.... non ui related
Log.v("response from saving",response);
if(response.equals("1")){
return true;
}else{
return false;
}
}
protected void onPostExecute(Boolean result) {
if(result) {
//------ UPDATE UI HERE
Toast.makeText(ProfileCompanyActivity.this, "profile saved", 2500).show();
}else{
Toast.makeText(ProfileCompanyActivity.this, "an error occured", 2500).show();
}
}
}
When you create a Aysnc task the doInBackground method runs in the separate thread from UI thread. So you cannot update the UI from this method.
The OnPostExecute and onPreExecute method execute in the same thread as UI thread. For further reading go here
If only one thread is allowed to touch the user interface, Android can guarantee that nothing vital is changed while it’s measuring views and rendering them to the screen
It is because .. User Interface can be updated only on mainthread..all the user interface objects in your screen are maintained by this mainthread....now if you try to change the user interface from some other thread(do in background)in this case.. it causes error because..for example.. if you try to change the seekbar(some widget) value from other than main thread.. and the user is trying to put a different value...then it is ambiguous for android.. as to which thread it should listen... hope it clarifies your doubt..
So, it is like we should'nt try to.. and because of its security.. we cannot try also.. as it gives error.. =]
doInBackground is used to perform heavy calculations or any background work you want to perform in your activity.
when the operation in your doinbackground method finished the on postexecute methods upadates your ui..
in short doinbackground is not used to update ui.
I think the answer is that we mustn't
It just doesn't seem logical to me..
its like trying to change the radio station at another car driving beside you..
the architecture just doesn't work that way.. you can decide on a radio station before you set off to your road trip or when you stop driving and theoretically you can yell to him and ask him to change the station but you cannot do it yourself.
As doInBackground() runs on separate thread and onPostExecute runs on UIMain thread and as per constraint provided by Android you cannot update UIMain Thread from other thread.
Because of above mentioned reason you are getting mentioned message while you are running your application.

How to execute some code in Android UI thread async?

I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!
There are several ways for doing that,
AsyncTask -
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. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.
You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}
Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3
You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}
Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};
The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.

ProgressDialog communicate with AsyncTask in android

Tips or ideas on how ProgressDialog can communicate with asyncTask.
For example when I click the button, the program will validate the input to internet, This is should not be interupted. so I use ProgressDialog.
After progressDialog.dismiss(), I need to refresh the view by calling the asyncTask.
I have tried some ways but it's failed, for example
* I execute asynTask after progressdialog.dismiss().
* put execution asynctask inside dialogbox after progressdialog thread.
in other word, is there any way to tell asynctask that progressdialog has been dismissed. Or is there communication such as message between threads ?
here is the example of my code:
btnPost.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stockProgressDialog = ProgressDialog.show(PostActivity.this,
"Please wait...", "Check the post");
new Thread() {
public void run() {
try{
/* Connect to Internet API */
stockProgressDialog.dismiss();
} catch (Exception e) { }
// Dismiss the Dialog
}
}.start();
new LookUpTask().execute();
}
});
Yes, there is a way to tell asyncTask that progressDialog has been dismissed. you can use one onDismissListener
#Override
public Dialog onCreateDialog(int id){
if(id==DIALOG_PROGRESS_DIALOG){
stockProgressDialog = new ProgressDialog(Main.this);
stockProgressDialog.setTitle("Please wait...");
stockProgressDialog.setMessage("Check the post");
stockProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
textView.setText("Waiting the 5 secs...");
myAsyncTask.execute("start it");
//Or myAsyncTask.cancel(true); if you want to interrupt your asyncTask
}
});
return stockProgressDialog;
} else return super.onCreateDialog(id);
}
You can cancel an AsyncTask by calling AsyncTask.cancel(..) and then start up a new AsyncTask. You are not supposed to run the AsyncTask as a parallel activity - it is supposed to be able to run and finish without outside intervention.
Extend async and look into returning a result from doInBackground. onProgress update can dismiss your Progress dialog under control of the async task. Handle the result from doInBackground in onPostExecute.
//create the task
theBackground = new Background();
theBackground.execute("");
--------
private class Background extends AsyncTask<String, String, String>{
protected String doInBackground(String...str ) {
publishProgress("##0");
//do a bunch of stuff
publishProgress(#001);
return("true");
}
protected void onProgressUpdate(String... str ) {
//do stuff based on the progress string and eventually
myProgressDialog.dismiss();
}
protected void onPostExecute(String result) {
}
}
I'm not sure why you're using a thread in one case, but an AsyncTask in another when you could just use two AsyncTasks... Actually, unless I'm missing something, in your case the most straightforward way is to combine the two bits of work into one AsyncTask and simply create and destroy the dialog in the AsyncTask callbacks. In pseudo-code:
onPreExecute
show dialog
doInBackground
do internet stuff
onPostExecute
update views
close dialog
Is there a reason why you're trying to update the views in its own AsyncTask? If you're updating views, you probably need to do the work in the UI thread anyway...

Categories

Resources