Android: Handler for AsyncTask - android

I use AsyncTask in combination with a ProgressDialog.
See my code, I have a problem in onPostExecute.
If the task is running for the first time it get a Null Poiter Exception for progressDialog in handleMessage but calling dismiss() direct would work.
When I turn the phone before onPostExecute is reached, progressDialog.dismiss() does not work. why does the handler not always work?
public class UpdateTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
private Handler handler;
public UpdateTask(Act activity) {
progressDialog = ProgressDialog.show(Activity.this, "Wait",
"Wait");
progressDialog.dismiss();
handler = new Handler(){
#Override
public void handleMessage(Message msg) {
//run on UI Thread
switch( msg.what ){
case MSG:
progressDialog.show();
break;
case DETACH:
progressDialog.dismiss();
break;
}
}
};
}
void detach() {
activity=null;
//problematic
//progressDialog.dismiss();
//handler.sendEmptyMessage(DETACH);
}
#Override
protected Void doInBackground(Void... params) {
handler.sendEmptyMessage(MSG);;
return null;
}
protected void onPostExecute(Void result) {
if (activity==null) {
Log.w("RotationAsync", "onPostExecute() skipped -- no activity");
}
else {
//problematic
// progressDialog.dismiss();
handler.sendEmptyMessage(MSG);
progressDialog = null;
}
}
};

Any reason why you need the Handler inside the AsyncTask? If you want to control your progress dialogue from an AsyncTask using a Handler is the correct way, however, your current Handler would get created and destroyed each time you start a new UpdateTask. If you define your handler outside your AsyncTask, something like:
private Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch( msg.what ){
case MSG:
progressDialog.show();
break;
case DETACH:
progressDialog.dismiss();
break;
}
return false;
}
});
Now you can call handler.sendEmptyMessage(what) from any background thread safely, and the progressDialog will update on the UI thread only. Not a complete fix, and I don't know what int values you have defined for DETACH and MSG. But hopefully it will help. This is the method I use to update any UI element from a background task. Just do a bit more reading about the AsyncTask and updating UI elements.

See https://stackoverflow.com/a/4538370/719212
And you should read about onPreExecute() in Android documentation.

Related

How to react to the end of a Thread

I have a log-in-Thread and while it is running i want to show up kind of a "loading-circle". So how can i recognize when the thread ends and react to it?
loadingcicle.setVisibility(View.VISIBLE);
Thread t = new Thread(new Einloggen());
t.start();
//and at the end
loadingcicle.setVisibility(View.GONE);
You probably want to use the asynctask pattern.
http://developer.android.com/reference/android/os/AsyncTask.html
something like
new AsyncTask<Void, Void, Void>() {
protected void onPreExecute() {
showProgress(true);
}
protected void void onPostExecute(Void result) {
hidProgress(true);
}
protected Void doInBackground(Void...voids) {
doMyBackgroundStuff();
}
}.executeOnExexutor(AsyncTask.THREAD_POOL_EXECUTOR);
of course you should be aware of activity lifecycle events and check that you are at least started or resumed before updating the ui.
You could instantiate a Handler object on your activity and pass it to your Einloggen class. So with this handler you can call Handler.post() to execute commands on UIThread.
Look at this reference: http://developer.android.com/reference/android/os/Handler.html
final android.os.Handler mHandler = new android.os.Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case 1:
//
Toast.makeText(context,"Responded !!!",Toast.LENGTH_LONG).show();
break;
}
return false;
}
});
new Thread(new Runnable() {
#Override
public void run() {
//do whatever you want here
mHandler.sendEmptyMessage(1);
}
}).start();

ProgressDialog in a separate thread

I have a procedure that extracts data from a database and populates it to the list. I want to display progress dialog box while query is executed, but it visually appears only after the query is executed. I believe I have to run a ProgressDialog in a separate thread, but followed few suggestions and could not make it work.
So in my Activity I just have
private void DisplayAllproductListView(String SqlStatement) {
ProgressDialog dialog =
ProgressDialog.show(MyActivity.context, "Loading", "Please wait...", true);
//..................
//..................
//execute sql query here
dialog.dismiss();
}
thanks
1.show your process dialog in main thread
2.start a new thread (such as Thread A) to process your heavy job
3.when done, use handler to send a message from Thread A to main thread, the latter dismisses the process dialog
code like this
private ProcessDialog pd;
private void startDialog()
{
pd = ProgressDialog.show(MainActivity.this, "title", "loading");
//start a new thread to process job
new Thread(new Runnable() {
#Override
public void run() {
//heavy job here
//send message to main thread
handler.sendEmptyMessage(0);
}
}).start();
}
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
}
};
Try something like this:
private class MyAwesomeAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog mProgress;
#Override
protected void onPreExecute() {
//Create progress dialog here and show it
}
#Override
protected Void doInBackground(Void... params) {
// Execute query here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//update your listView adapter here
//Dismiss your dialog
}
}
To call it:
new MyAwesomeAsyncTask().execute();
All you need to do, is to tell Android to run it on the main UI thread. No need to create a Handler.
runOnUiThread(new Runnable() {
public void run() {
progressDialog.dismiss();
}
});

Preload progressDialog makes my app crash only in ICS

So I'm using this code to show the message "Installing..." while the database is setup with the function 'setUpDB' and is then removed when the database function has completed. This works fine in Gingerbread and honeycomb, but causes the application to crash in ICS
final ProgressDialog pd=ProgressDialog.show(this,"","Installing...");
final Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
pd.dismiss();
}
}
};
//have subcategory heading???
Thread thread = new Thread()
{
#Override
public void run() {
setUpDB();
handler.sendEmptyMessage(0);
}
};
thread.start();
Without dismissing the message, the app will continue to run in ICS (but you can't do anything), and without displaying the message if the user does anything that accesses the database before it is finished being setup it will crash (thus why I need the installing message)..
Okay, here is the code using AsyncTask
final ProgressDialog pd=ProgressDialog.show(this,"","Installing...");
final Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
pd.dismiss();
}
}
};
new databaseInstallTask().execute(handler);
And
private class databaseInstallTask extends AsyncTask<Handler, Void, Handler>
{
#Override
protected Handler doInBackground(Handler... params) {
setUpDB();
return params[0];
}
protected void onPostExecute(Handler handler) {
handler.sendEmptyMessage(0);
}
}
Why don't you try using Asynctask which I suppose is the most appropriate way to handle your case.

ProgressDialog while load Activity

I found this code in SO to show ProgressDialog while load Activity:
progDailog = ProgressDialog.show(MyActivity.this, "Process", "please wait....", true, true);
new Thread(new Runnable() {
public void run() {
// code for load activity
}).start();
Handler progressHandler = new Handler() {
public void handleMessage(Message msg1) {
progDailog.dismiss();
}
};
But I always get this exception:
java.lang.RuntimeException: Can't create handler inside thread that
has not called Looper.prepare()
I appreciate any help for this issue, thanks in advance.
Here is what I would do,
AsyncTask to do the "heavy work" in background:
public class MyTask extends AsyncTask<String, String, String> {
private Context context;
private ProgressDialog progressDialog;
public MyTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(context);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
//Do your loading here
return "finish";
}
#Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
//Start other Activity or do whatever you want
}
}
Start the AsyncTask:
MyTask myTask = new MyTask(this);
myTask.execute("parameter");
Of course you can change the generic types of the AsyncTask to match your problems.
The problem is because you are trying to create Handler inside a worker Thread. It is not possible. Create your Handler inside of onCreate() or somewhere else on the main UI. And you can send message to your handler from your Worker Thread.
This is because Android doesn't allow you to modify the UI from any other Thread other than the Main UI thread itself.
You need to create your handler on the main thread rather than inside OnClick.

Android: Thread with progressBar and setcurrentTab

final ProgressDialog Pdialog = ProgressDialog.show(SpinnerClass.this, "",
"Loading. Please wait...", true);
Thread ProgressThread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
Pdialog.dismiss();
} catch(InterruptedException e) {
// do nothing
} finally {
}
}
};
ProgressThread.start();
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
The problem I have with this thread is that it sets the current tab before the progress dialog starts. What have i done wrong ?
I want the dialog to run and dismiss, and after thread is done set tab.
use AsyncTask for this
some hints:
public class BackgroundAsyncTask extends AsyncTask<Void, Integer, Void> {
int myProgress;
#Override
protected void onPostExecute(Void result) {
TabHost1 tab = new TabHost1();
tab.tabHost.setCurrentTab(2);
progressBar.dismiss();
}
#Override
protected Void doInBackground(Void... params) {
while(myProgress<100){
myProgress++;
publishProgress(myProgress);
SystemClock.sleep(100);
}
return null;
}
#Override
protected void onProgressUpdate(Integer p) {
progressBar.setProgress(p);
}
}
The thing is that,you are starting a thread which will not affect your main UI. So what eventually happens is that, your thread will run separately which will now allow the next lines of your code to be executed. So in your case,
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
these lines will be executed irrespective to your thread which is also getting executed simultaneously. So what you can do here is you can either go for AsyncTask or create handlers to handle this part of your code. You have to change your code like this.
Do this in your onCreate()
Handler handler;
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
Pdialog.dismiss();
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
}
};
And now in your thread,call the handler like this,
final ProgressDialog Pdialog = ProgressDialog.show(SpinnerClass.this, "",
"Loading. Please wait...", true);
Thread ProgressThread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
} catch(InterruptedException e) {
// do nothing
} finally {
handler.sendEmptyMessage(0);
}
}
};
this will allow your tabhost to wait until the thread gets executed and will come into view after thread finishes execution.

Categories

Resources