I have this problem: during a long operation, I display a ProgressBar. Sometimes, during this operation, the programm has to ask the user for somewhat.
Then, I'd like to display a DialogBox, but if I do that, I get an error, since a DialogBox cannot be displayed during a Thread.
How can I solve my problem?
Please use AsyncTask Instead of thread then it will work you cannot perform UI related work in thread.
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.
Read about AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
Android supports the usage of the standard Java Thread class to perform asynchronous processing.
Android also supplies the java.util.concurrent package to perform something in the background, e.g. using the ThreadPools and Executor classes.
If you need to update the user interface from a new Thread, you need to synchronize with the user interface thread.
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
i think this is what u want.
To start the operation:-
new StartTask().execute("");
StartTask Class:-
public class StartTask extends AsyncTask<String, Integer, String> {
private ProgressDialog pdialog;
#Override
protected void onPreExecute() {
// UI work allowed here
pdialog = new ProgressDialog(syncContext);
// setup dialog here
pdialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pdialog.setMessage("Updating...");
pdialog.setCancelable(false);
pdialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
if(pdialog != null) {
pdialog.dismiss();
}
if(progress[0] == 0) {
AlertDialog.Builder alertbox = new AlertDialog.Builder(context);
alertbox.setCancelable(false);
alertbox.setMessage("This is first Alert").setPositiveButton("OK",
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
pdialog.show();
}
});
alertbox.create();
alertbox.show();
} else if(progress[0] == 1) {
AlertDialog.Builder alertbox = new AlertDialog.Builder(context);
alertbox.setCancelable(false);
alertbox.setMessage("This is second Alert").setPositiveButton("OK",
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
pdialog.show();
}
});
alertbox.create();
alertbox.show();
}
}
#Override
protected void onPostExecute(String returnVal) {
// UI work allowed here
if(pdialog != null) {
pdialog.dismiss();
}
}
#Override
protected String doInBackground(String... params) {
for(int i = 0; i < 3; i++) {
//do some work here
publishProgress(i);
}
}
}
Related
When I create AlertDialog in backgroud background thread AsyncTask, I get error. if I create AlertDialog outside of AsyncTask its working great. How I can fix that?
final ProgressDialog mDialog = new ProgressDialog(PageAndExercise.this);
mDialog.setMessage(getString(R.string.loading));
mDialog.setCancelable(false);
mDialog.show();
alertDialog2 = new AlertDialog.Builder(this);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
mDialog.dismiss();
alertDialog2.setTitle(getString(R.string.tnxupload));
// Setting Dialog Message
alertDialog2.setMessage(getString(R.string.tnxupload2));
alertDialog2
.setCancelable(false)
.setPositiveButton("", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
})
.setNegativeButton(getString(R.string.tnxupload3), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialog2.create();
// show it
alertDialog2.show();
}
});
The error:
28928-31794/com.example.exampleE/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #5
Process: com.example.example, PID: 28928
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
You should look more into what AsyncTask does and why.
It is a convenience class to allow work to be done in the background. The doInBackground method allows long-running work to not block the UI thread.
However, if you want to display or perform tasks on the UI thread, you need to make sure those happen on the UI thread. For example, your line:
mDialog.dismiss();
should execute in onPreExecute because it impacts the UI. Likewise:
alertDialog2.show()
is trying to change the UI. This should be run in onPostExecute.
Fundamentally, though, building an AlertDialog is not a long running task at all. None of that needs to be in AsyncTask unless you have intentions to expand what happens prior to displaying the next dialog.
See this post here: http://blog.nikitaog.me/2014/10/11/android-looper-handler-handlerthread-i/
You can't interact with UI non from main-Thread.
The short solution here is:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// Call UI related methods.
}
});
I guess AsyncTask implement to your code is something like this:
final ProgressDialog mDialog = new ProgressDialog(this);
mDialog.setMessage("loading");
mDialog.setCancelable(false);
mDialog.show();
final AlertDialog.Builder alertDialog2 = new AlertDialog.Builder(this);
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
mDialog.dismiss();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
AlertDialog alertDialog = alertDialog2.create();
alertDialog2.setTitle("tnxupload");
alertDialog2.setMessage("tnxupload");
alertDialog2.setCancelable(false).setPositiveButton("", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
}).setNegativeButton("tnxupload3", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
alertDialog2.show();
}
#Override
protected Void doInBackground(Void... params) {
return null;
}
}.execute();
I use AsyncTask in my App for download a url. I use a ProgressDialog on onPreExecute() for waiting.
But I cant see ProgressDialog while process finish and i see it for a moment. want to see it while downloading not after that.
can any one help me.
thanks
my code is like this:
private class loadMoreListView extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
// Showing progress dialog before sending http request
pDialog = new ProgressDialog(SingleMenuItemActivity.this);
pDialog.setMessage("Please Wait ...");
pDialog.isIndeterminate();
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(Void... unused) {
runOnUiThread(new Runnable() {
public void run() {
// do something for downloading
}
});
return (null);
}
protected void onPostExecute(Void unused) {
// closing progress dialog
pDialog.dismiss();
}
}
runOnUiThread(new Runnable() {
public void run() {
// do something for downloading
}
// do something for downloading, inside runOnUiThread, is wrong. runOnUiThread makes "do something for downloading" run on the UI Thread, and your application should crash for NetworkOnMainThreadException, you the app runs on a device with a version of android grater than GingerBread. Differently it will block the ui thread preventing him to draw your progress bar
The problem is in
runOnUiThread(new Runnable() {
public void run() {
// do something for downloading
}
});
ProgressDialog will not update if the UI thread is still busy. There are many examples in SO for that.
I don't understand why do you need UIthread.
And as a rule of thumb - if you need Progress dialog, you need to let run asynctask in background thread,as it always do.Read the document
http://developer.android.com/reference/android/os/AsyncTask.html
You can use the below example
http://www.androidhive.info/2012/01/android-json-parsing-tutorial/
Firstly notice the "#override" header attached to all the AsyncTask Implemented methods e.g.
private class loadMoreListView extends AsyncTask<Void, Void, Void> {
ProgressDialog pDialog;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
pDialog = new ProgressDialog(SingleMenuItemActivity.this);
pDialog.setMessage("Please Wait ...");
pDialog.isIndeterminate();
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pDialog.cancel();
}
}
Also Remove this from doInBackground unless you must do something on the UI.
runOnUiThread(new Runnable() {
public void run() {
// do something for downloading
}
});
You cannot do something for downloading on the runOnUiThread. doInBackground is meant for running background tasks like downloads etc. not visible to the UI.
I am developing an Android app which has 2 classes. Game, which extends Activity, and GameView, which extends View.
When the game is loaded, it sets the content view to GameView, which is just a drawing class that uses a canvas to display the game.
I am trying to create a ProgressDialog in the Game class which will show a spinner after a certain action has been done, as this takes a long time to complete. So far I have the following:
setContentView(R.layout.activity_game);
ProgressDialog pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setMessage("Calculating hint");
pd.show();
AsyncTask<String[][], Void, SudokuSquare> nextSquareThread = new GetNextSquare().execute(puzzleNumbers);
next = nextSquareThread.get();
pd.dismiss();
setContentView(gameView);
And my AsyncTask class looks like this:
private class GetNextSquare extends AsyncTask<String[][], Void, SudokuSquare> {
private ProgressDialog dialog = new ProgressDialog(Game.this);
#Override
protected void onPreExecute() {
this.dialog.setMessage("Finding next number");
this.dialog.show();
}
#Override
protected SudokuSquare doInBackground(final String[][]... args) {
try {
SudokuAdvancedSolver solver = new SudokuSolver(args[0]);
return solver.getOneValue();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#Override
protected void onPostExecute(final SudokuSquare result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
At the moment I have two ProgressDialogs, one inside the AsyncTask and one outside. Which one is correct? Also, the spinner is not being displayed at all. What am I overlooking which is causing this to be the case?
only the one outside is correct. because you are trying the main thread (the UI thread of your activity) by another thread (your asychronic task). you should use a handler in place of this :
1/ you show the progress bar
2/ you load the game in a thread
3/ when the game is loaded you send a message to the handler which will stop the progress bar.
See this exemple . you should dismiss your dialog in the handler (when the handler receives the message from the thread) .
If you don't implement a listener on Asynctask, i could suggest you to dismiss your progress dialog onPostExecute
private ProgressDialog dialog;
public void setProgressDialog(ProgressDialog dialog){
this.dialog = dialog;
}
#Override
protected void onPostExecute(final SudokuSquare result) {
dialog.dismiss();
}
and before you executing Asynctask add this code
nextSquareThread.setProgressDialog(pd);
in the past few days I have been trying to figure something but had no luck, I am developing an android game, I have 3 packages for now each with its own purpose:
1 - package for GUI classes.
2 - package that has classes communicates with my wcf service (login/pass DB)
3 - package that holds my asynchronous classes/workers (like a bridge between GUI and SERVICE)
I am not sure if this is even the right approach when it comes to android/java game development, but what I want to achieve is a simple registeration/login in the GUI and when the user is done registering or logining, while the gui talks to the service through the "bridge", a message is displayed for the user like a dialog saying "registering" or "loging in".
Now I would like to hear tips/feedback from more experienced programmers, on how to acomplish this, and if this is the right aproach, and most importantly some examples for this specific case would be really helpfull, I tried to work with the asynctask but I couldn't figure out how to communicate between these 3 seperate packages and return the result from the service back to the gui through the async task.
Take a look at this
public class FindEventsActivity extends Activity {
ProgressDialog pd;
// lots of other code up here
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clickete);
pd = new ProgressDialog(this);
pd.setMessage("loading");
findViewById(R.id.clickLayout).setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
new LongOperation().execute("");
pd.show();
}
});
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 15; i++) {
try {
Thread.sleep(1000); // Simulates your intensive work
// Update your progress if you want
this.publishProgress();
} catch (InterruptedException e) {
return "Failed";
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
// Handle fail or success accordingly
pd.dismiss();
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
// Update UI according to your progress
}
}
}
Hope this helps and enjoy your work
My application has a ViewFlipper with 3 ViewGroups in it. Each ViewGroup interaction is dependent on data from a database. I'm using an AsyncTask to read from a database and return a Cursor when it's done. Before the AsyncTask is executed, I just want to display a single View in the ViewFlipper saying "Loading data, please wait.", is this possible somehow?
Show the progress dialog in your onPreExecute() and dismiss it in the onPostExecute(). Something like this,
private class MyAsyncTask extends AsyncTask<Integer, Integer, Integer[]> {
private ProgressDialog myWait = null;
// This is on the UI thread itself
protected void onPreExecute() {
myWait = new ProgressDialog(MainActivity.this);
myWait.setMessage("Loading data, please wait");
myWait.setCancelable(false);
myWait.show();
}
// Separate worker thread is used here
protected Integer[] doInBackground(Integer...params) {
//do the database loading
return <your result - goes to onPostExecute>;
}
// This is on the UI thread itself
protected void onPostExecute(Integer[] resultCell) {
if (myWait != null) {
myWait.dismiss();
}
}
}
yes you can make use of progressDialog. Do it like this,
progressDiaolg=ProgressDialog.show(Activity.this,"","Loading Images...");
final Thread t= new Thread(new Runnable() {
public void run() {
Log.i("Inside Thread", "Downloading Images...");
downloadImages();
handler.sendEmptyMessage(0);
}
});
t.start();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
progressDiaolg.dismiss();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
};
I don't have idea with Asynctask. So try modifying this snippet accordingly.