I am trying to call AlertDialog into AsyncTask. I wrote this code and it works, but when I choose item in the AlertDialog and then call uiHandler.getLooper().quit(); to continue code proccesing, AlertDialog is freezes (doesnt closing, staying until activity finishes) but backgroundUI continue proccesing. I think it's because AlertDialog has no time to perform dismiss() method before infinity loop is ending. Please, help me to solve this problem. I need to do this only in doInBackground method.
#Override
protected Void doInBackground(Void... arg0) {
Looper.prepare();
final Handler uiHandler = new Handler();
uiHandler.post(new Runnable() {
public void run() {
AlertDialog.Builder chooser = new AlertDialog.Builder(ctx);
facultyChooser.setTitle("Choose")
.setCancelable(false)
.setItems(faculties, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
uiHandler.getLooper().quit();
}
})
.create()
.show();
}
});
Looper.loop();
}
PS: It's not full code for easier reading.
You have to run you alert before the doInBackground (onPreExecute) and dismiss your dialog after it (onPostExecute)
Technically, It is not passible to do UI related task in doInBackground() method on Asyntask. You have to use onPostExecute()/onPreExecute() of Asyntask for showing AlertDialog.
Related
How to cancel a AsyncTask from a ProgressDialog implemented within this AsyncTask.
#Override
protected Void doInBackground(Void... params)
{
try
{
FTPHelper ftpHelper = new FTPHelper(_context);
ftpHelper.SincronizarArquivos();
}
catch...
#Override
protected void onPreExecute()
{
_dialog.setMessage("Aguarde, sincronizando arquivos...");
_dialog.setCancelable(false);
_dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancelar", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
// This not works for cancel AsyncTask
cancel(true);
...
Since there is no loop in doInBackground (Void ... params) has as I cancel or return. How can I cancel AsyncTask from ProgressDialog?
Both the dialog and the AsyncTask have a 'cancel' method, so when you call cancel in the dialog it cancels the dialog.
The solution is for the dialog to call the cancel function of the AsyncTask. From the code in the question I can't quite infer the way the dialog and the task are linked in the code, but in essence, if ...
AsyncTask myAT;
Then within the dialog:
myAT.cancel();
Call
MyAsyncTask.this.cancel(true);
inside the Dialog.
Here MyAsyncTask is the name of your AsyncTask subclass.
NOTE: This will work (only) if the Dialog was instantiated inside the AsyncTask
I am using Parse in my android app and want to block the UI with a dialog while the query runs to get the data. I first create and show a dialog and then do the ParseQuery.find(). However, the dialog never shows up on the UI. Am I missing something?
//Show Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(mCtx);
builder.setTitle("Some Title...")
.setMessage("Please wait...")
.setCancelable(false);
dialog = builder.create();
dialog.show();
List<ParseObject> objects;
try {
objects = query.find();
//read is successful
if (objects != null && objects.size() > 0) {
...........
........
dialog.cancel();
......................
Yes unfortunately you are missing something.
I am assuming that you are calling your code on the main thread, first dialog.show() and then doing query.find() after that.
Your problem is that you are (probably) doing all this work on the main thread, and the dialog will not show until the main thread has time to parse your .show() command. But since you are blocking the main thread by doing query.find() it won't show until that code has finished executing.
You should solve this problem by doing your query on the background thread, e.g. using AsyncTask, Thread, or some other method.
Let me show you how to do it using thread.
public class MainActivity extends Activity {
AlertDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Show Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(mCtx);
builder.setTitle("Some Title...").setMessage("Please wait...").setCancelable(false);
dialog = builder.create();
dialog.show();
new Thread() {
public void run() {
// Do you heavy lifting
List<ParseObject> objects;
try {
objects = query.find();
// read is successful
if (objects != null && objects.size() > 0) {
}
} catch (Exception e) {
}
// Since we are in a thread you need to post the cancel on the
// main thread, otherwise you'll be in trouble.
runOnUiThread(new Runnable() {
public void run() {
dialog.cancel();
}
});
}
}.start();
}
}
Hopefully you'll find my answer helpful!
Best Regards,
Erik
I have this code and it goes to catch as soon as it hits Source.httpConn and it sends the exception down below to catch.
try
{
JSONTokener sbTokener = new JSONTokener(Source.httpConn(infoUrlStr, Main.this).toString());
//array için hazırlandı
JSONArray jArray=new JSONArray(sbTokener);
//arraye eklendi
for(int i=0; i<(jArray.length()); i++)
.
.
.
}
Down in the catch part there is my alert dialog method. It normally works pretty well but I suspect that I have the problem because of the doInBackground. The application crashes before displaying the below alert dialog. All the try-catch is in my doInBackground method in ASyncTask.
catch (Exception e) {
AlertDialogDisp(Main.this, noServ, noServLog);
}
How can I make my application NOT crash and just display this alert dialog and then return to my Main activity as it was. Here is my alert dialog method:
protected void AlertDialogDisp(Context dialogContext, String head, String log) {
new AlertDialog.Builder(dialogContext)
.setTitle(head)
.setMessage(log)
.setPositiveButton("okay", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// On Alert Dialog Button
dialog.dismiss();
}
})
.show();
}
You cannot update ui from doInbackground. doInbackground is invoked on a backgroudn thread. Ui should be updated on the ui thread. Return result in doInbackground and update ui in onPostExecute
For more info check the docs
http://developer.android.com/reference/android/os/AsyncTask.html
You can also use runOnUithread which is a method of activity class
runOnUiThread(new Runnable(){
public void run() {
// dispaly dialog here
// no network related operation here
}
});
Show your dialog in runOnUiThead which is a method of activity class.
runOnUiThread(new Runnable(){
public void run() {
//write your alert dialog code here
}
});
I have a Button, and upon pressing it, the onClick() would process user's request. However, this takes a little time, so I would like to have a View showing "Please wait, processing..." immediately upon pressing this Button, while its OnClickListener does its thing.
My problem is, this "Please wait, processing..." which I placed at the very beginning of onClick(), only appears AFTER the whole onClick() is done. In other words, after the whole processing is done. So, I was wondering, how do I make a View saying "Please wait, processing..." before the actual processing has begun?
As #Blundell pointed you may process long-running operation on a separate thread to avoid freezing of UI thread. However in Android there's a better alternative for general-purpose Handler which is called AsyncTask. Please refer to this tutorial for details.
You can do this by just using AsyncTask without dealing anything else.
First create new AsyncTask class on "onPreExecute" change ui to show
that you are processing sth
Second do your all backend time consuming job on "doInBackground"
method (do not call any ui updating method from here)
Third change your ui to show that process is finished or whatever you
wanna do.
yourUiButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
new NewTask().execute();
}
});
class NewTask extends AsyncTask<String, Void, Task>{
#Override
protected void onPreExecute() {
super.onPreExecute();
//this part runs on ui thread
//show your "wait while processing" view
}
#Override
protected Task doInBackground(String... arg0) {
//do your processing job here
//this part is not running on ui thread
return task;
}
#Override
protected void onPostExecute(Task result) {
super.onPostExecute(result);
//this part runs on ui thread
//run after your long process finished
//do whatever you want here like updating ui components
}}
Do the processing on another thread so that the UI can show your dialog.
// Show dialog
// Start a new thread , either like this or with an ASyncTask
new Thread(){
public void run(){
// Do your thang
// inform the UI thread you've finished
handler.sendEmptyMessage();
}
}
When the processing is done you will need to callback to the UI thread to dismiss oyur dialog.
Handler handler = new Handler(){
public void handleMessage(int what){
// dismiss your dialog
}
};
AsyncTasks.
Place the displaying of the progress dialog in onPreExecute
Do your thing in doInBackground
Update whatever needs to be updated in the UI, and close the dialog in onPostExecute
You will need something like this
public void onClick(View v){
//show message "Please wait, processing..."
Thread temp = new Thread(){
#Override
public void run(){
//Do everything you need
}
};
temp.start();
}
or if you want it to run in the UIThread (since it is an intensive task, I don't recommend this)
public void onClick(View v){
//show message "Please wait, processing..."
Runnable action = new Runnable(){
#Override
public void run(){
//Do everything you need
}
};
v.post(action);
}
put ur code inside a thread and use a progress dialogue there...
void fn_longprocess() {
m_ProgressDialog = ProgressDialog.show(this, " Please wait", "..", true);
fn_thread = new Runnable() {
#Override
public void run() {
try {
// do your long process here
runOnUiThread(UI_Thread);//call your ui thread here
}catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(null, thread1
"thread1");
thread.start();
}
then close your dialogue in the UI thread...hope it helps..
I have an AsyncTask that get info from the web. Sometimes the connection fails and the AsyncTask processdialog is running forever.
In the doInBackground I have a check in the end if my catched info are empty and if this is the case, it should appear Positive button/Negative button, but this is not happening. The dialog is just running.
How can I check if an AsyncTask is taking too long time (Maybe 5 seconds) and dismiss the dialog?
Code snippet (doInBackground):
//orders is my ArrayList<Order> object, from my own Order class.
if(orders==null) {
pdia.dismiss();
AlertDialog.Builder alt_bld = new AlertDialog.Builder(ctx);
alt_bld.setMessage("Try agin?")
.setCancelable(false)
.setPositiveButton("Try again", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
button_refresh.setVisibility(View.GONE);
new ListTask().execute(null, null , null);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = alt_bld.create();
alert.setTitle("Connection failed!");
alert.show();
}
else {
return orders;
}
Thanks in advance and tell me if you need more info!
Instead of checking your result in doInBackground() you can get the value from the process and check it in onPostExecute(), like this:
protected void onPostExecute(ArrayList<Order> localOrders){
super.onPostExecute(localOrders);
if (localOrders==null) {
// Paste the positive and negative DialogListeners here
// and dismiss the dialog.
}
}
The result from your doInBackground() process passes into onPostExecute's parameter, thence you can check if your ArrayList object is empty or not.
But then writing the above code snippet in the onPostExecute will defeat the purpose right? We want the user to not wait past 5 seconds for an answer from the webservice and therefore we must handle the timeout within doInBackground itself.