I am opening a progressdialog with AsyncTask in doInBackground method the question is loading from database and after question successfully loaded the progress dialog box will be closed
but my problem is some time I am getting following error
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRoot$W#44757528 is not valid; is your activity running?
by doing some googling I have found that there may be i am holding on to a reference to a Context (either explicitly, or by creating a Dialog or Toast or some other dependent item) that has been destroyed (typically because you are using the onCreateDialog or you passed the Activity to some other process that didn't get destroyed when the Activity was destroyed).
So I have put below code that dismiss progressdialog in-case if activity is destroyed before dialog box is dismissed
protected void onDestroy() {
if (pdForNewQuestion != null)
pdForNewQuestion.dismiss();
super.onDestroy();
}
but I still face the issue. I am not destroying any activity but still the error suddenly comes sometimes and sometimes it works properly
the async code is below
// Start new question in every 60 seconds :)
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
mProgressStatus++;
} catch (Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
txtCountingNum.setText((timer--) + "\nSec.");
if (timer < 0) {
questionLoadWithAsyncTask();
}
}
});
}
}
}).start();
public void questionLoadWithAsyncTask() {
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
pdForNewQuestion = new ProgressDialog(QuizActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... arg0) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result) {
if (pdForNewQuestion != null) {
pdForNewQuestion.dismiss();
}
}
}.execute();
}
Check whether the dialog is showing or not if dialog is showing then only dismiss like this..
#Override
protected void onDestroy() {
if (pdForNewQuestion != null) {
if (pdForNewQuestion.isShowing()) {
pdForNewQuestion.dismiss();
pdForNewQuestion = null;
}
}
super.onDestroy();
}
you are running infinite loop inside new Thread but not breaking the loop and stopping that Thread. It runs infinitely in the background even when activity goes background. try stopping the Thread once work is finished.
First of all why are you starting your AsyncTask inside a Thread? As i understand you are trying to start an AsyncTask every 60 seconds and populate a new question. There is a much better way to do this using only a Handler and AsyncTask.
Create a Handler and post Runnable which runs every seconds and depending on the result start your AsyncTask :
int mSeconds = 0;
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(mSeconds == 60){
new QuestionLoader().execute();
mSeconds = 0;
}
mHandler.postDelayed(this, 1000);
mSeconds++;
}
}, 1000);
and you can create your AsyncTask like this :
private class QuestionLoader extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
super.onPreExecute();
pdForNewQuestion = new ProgressDialog(MainActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... params) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
if(pdForNewQuestion != null && pdForNewQuestion.isShowing()){
pdForNewQuestion.dismiss();
}
}
}
This is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. Then check that the activity is not closed by some other apps or other triggers before showing the dialog
if (!isFinishing()) {
//showdialog here
}
Related
class TestAsync extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
v.findViewById(R.id.loadinglayout).setVisibility(View.VISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.INVISIBLE);
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
callAPI();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
v.findViewById(R.id.loadinglayout).setVisibility(View.INVISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.VISIBLE);
}
}
public void callAPI ()
{
RequestInterface requestInterface = new RequestImplementation();
requestInterface.setUrl("https://api.myjson.com/bins/vl9pp");
ConnectionExecutor connectionExecutor = new
ConnectionImplementation();
ResponseInterface temp = null;
try {
temp = connectionExecutor.executeConnection(requestInterface);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
rangeText.setText(temp.getPayload());
}
Call API function will call a method of another class where HttpConnection is done.
If the function is directly called from onViewCreated() in fragment then it works. If I call it from another async task it returns nothing.
I am actually trying to show a progress bar when the callApi function is called.
It is not allowed to start an AsyncTask outside the UI thread. doInBackground is outside the UI thread.
From https://developer.android.com/reference/android/os/AsyncTask.html:
Threading rules
...
The AsyncTask class must be loaded on the UI thread.
call it on onPostExecute method
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
v.findViewById(R.id.loadinglayout).setVisibility(View.INVISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.VISIBLE);
callAPI();
}}
From this SO answer
only inside onProgressUpdate() or onPostExecute() since these methods
runs on the UI thread. Therefore, start the second AsyncTask on the UI
thread by choosing one of the two methods listed above.
Simply put, if you're in need of firing up AsyncTask within another AsyncTask, it must be called from either onProgressUpdate() or onPostExecute() since they resides in UI thread.
To show the ProgressBar to illumilate the task is running, you should show your progress bar in onPreExecute() and hide it in onPostExecute(Result).
AsyncTask<Void, Void, Void> yourTask = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
/**
* Show your progress bar:
*/
yourProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
/**
* Do your stuffs in background thread
*/
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
/**
* Hide your progress bar:
*/
yourProgressBar.setVisibility(View.GONE);
}
};
Run the task: yourTask.execute();
onPostExecute(Result) method will get called when the task completed.
I have 2 activities, 1 called MainActivity, and the other called Circle. I want to have a progress bar loading screen come up when I click a button on the MainActivity to launch a second one. Here is the code that I have at the moment but it just causes the app to crash.
public class LoadingScreenActivity extends Activity
{
//A ProgressDialog object
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Initialize a LoadViewTask object and call the execute() method
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in the separate thread
#Override
protected void onPreExecute()
{
//Create a new progress dialog
progressDialog = new ProgressDialog(LoadingScreenActivity.this);
//Set the progress dialog to display a horizontal progress bar
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//Set the dialog title to 'Loading...'
progressDialog.setTitle("Loading...");
//Set the dialog message to 'Loading application View, please wait...'
progressDialog.setMessage("Loading application View, please wait...");
//This dialog can't be canceled by pressing the back key
progressDialog.setCancelable(false);
//This dialog isn't indeterminate
progressDialog.setIndeterminate(false);
//The maximum number of items is 100
progressDialog.setMax(100);
//Set the current progress to zero
progressDialog.setProgress(0);
//Display the progress dialog
progressDialog.show();
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
/* This is just a code that delays the thread execution 4 times,
* during 850 milliseconds and updates the current progress. This
* is where the code that is going to be executed on a background
* thread must be placed.
*/
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(850);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
//set the current progress of the progress dialog
progressDialog.setProgress(values[0]);
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
//close the progress dialog
progressDialog.dismiss();
//initialize the View
setContentView(R.layout.content_circle);
}
}
}
You can add some default view like progressbar in second activity XML that is visible by default. When you load data or whatever you do set it to view.GONE. Nice library like this :
https://github.com/81813780/AVLoadingIndicatorView
In your second_activity.xml use :
<com.wang.avi.AVLoadingIndicatorView
android:layout_gravity="center"
android:id="#+id/avloadingIndicatorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:indicatorName="BallPulse"
app:indicatorColor="#color/myPrimaryColor"/>
Then in your activity onCreate() method :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loader= (AVLoadingIndicatorView) findViewById(R.id.avloadingIndicatorView);
}
And finally when you finish the loading just use :
loader.setVisibility(View.GONE);
First create a common Class Utility for ProgressDialog to reuse the code
public class Utility {
public static ProgressDialog getProgressDialog(Context context) {
ProgressDialog progressDialog = new ProgressDialog(context,
R.style.TransparentDialog);
progressDialog.setCancelable(false);
progressDialog
.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
progressDialog.setProgress(0);
return progressDialog;
}
}
Then Use the Above class in your activity or fragment. But you have to use to Intent for go to next activity. you can't directly set the next activity layout
public class LoadingScreenActivity extends Activity
{
//A ProgressDialog object
protected ProgressDialog dialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Initialize a LoadViewTask object and call the execute() method
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in the separate thread
#Override
protected void onPreExecute()
{
super.onPreExecute();
dialog = Utility.getProgressDialog(context);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
if (dialog != null) {
dialog.show();
}
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
/* This is just a code that delays the thread execution 4 times,
* during 850 milliseconds and updates the current progress. This
* is where the code that is going to be executed on a background
* thread must be placed.
*/
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(850);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
//close the progress dialog
dialog.dismiss();
// use intent here to go next activity
Intent i = new Intent(this,SecondActivity.class);
startIntent(i);
}
}
I have a simple Android AsyncTask with a long background action:
HANDLER.post(new Runnable() {
#Override
public void run() {
new AsyncTask<Context, Integer, GameTypeAdapter>() {
#Override
protected GameTypeAdapter doInBackground(Context... contexts) {
return new GameTypeAdapter(contexts[0]);//Long database action
}
#Override
protected void onPreExecute() {
pbWaiter.setVisible(View.VISIBLE);
}
#Override
protected void onPostExecute(GameTypeAdapter gameTypeAdapter) {
txtGameName.setText(settings.getGameName());
cmbType.setAdapter(gameTypeAdapter);
if (settings.getGamePlugin() != null) {
cmbType.setSelection(((GameTypeAdapter) cmbType.getAdapter()).getItemPosition(settings.getGamePlugin()));
}
sldJoker.setProgress(settings.getJoker());
pbWaiter.setVisible(View.INVISIBLE);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
}
});
If the method onPostExecute is called by thread and the last line (hideWaiter) was called the execution of the UI calls are visible after 1/10 seconds (a half second in debug mode). In this time the UI hangs and the waiter animation stops.
Why the UI thread stops?
Thanks.
I've got a quite interesting issue when I try to display a ProgressDialog (the simple, spinner type) within a onPreferenceChange listener.
public class SettingsActivity extends PreferenceActivity {
private ProgressDialog dialog;
public void onCreate(Bundle savedInstanceState) {
ListPreference pref= (ListPreference) findPreference("myPreference");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
dialog = ProgressDialog.show(SettingsActivity.this, "", "Doing stuff...", true);
SystemClock.sleep(2000);
}
return true;
}
}
The ProgressDialog shows up, but not until the method (sleep in this case) has finished. What am I doing wrong?
You're sleeping on the main UI thread, which stops the operating system from handling your application's events. This will stop your app from redrawing and as you discovered, can prevent new windows from actually appearing.
Instead of sleeping, try this:
final ProgressDialog dialog = ProgressDialog.show(
SettingsActivity.this, "", "Doing stuff...", true);
new Handler().postDelayed(new Runnable() {
public void run() {
dialog.hide();
}
}, 2000);
You can use AsyncTask to run the function in a separate thread (see http://developer.android.com/resources/articles/painless-threading.html)
This is probably a bit unnecessary if you just want to invoke a sleep method, but should work even for other methods that otherwise would block the UI thread.
You could do something like this:
private class BackgroundTask extends AsyncTask<Integer, Integer, void> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(SettingsActivity.this, "", "Doing stuff...", true);
}
#Override
protected void doInBackground(Integer... params) {
sleep(params[0]);
}
#Override
protected void onPostExecute(Boolean result) {
dialog.dismiss();
}
}
And than call it using the code below:
new BackgroundTask().execute(2000);
I have a little problem, I hope U can help me;)
Trouble is, that ProgressDialog show only after loading run(), but I need to show it on start and showing it while loading some data. I put: "dialog = ProgressDialog.show(CategoriesListActivity.this,"Working...","Loading data", true);" in method run(), but the same. I print in Log.i() some info (int i++) and put title of ProgressDialog. Method work correctly, but don't show ProgressDialog. I have read some info that some thread block another thread (my created), that's why doesn't show progressDialog, but can't do anything. Thx.
public void run() {
/** getting there long execution **/
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// stop and hide dialog
dialog.dismiss();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_
dialog = ProgressDialog.show(CategoriesListActivity.this, "Working...",
"Loading data", true);
// start new thread where get long time execution
Thread thread = new Thread(this);
thread.start();
//wait while data is loading, 'cause I need use variable from calculation
// in "EfficientAdapter" later
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
ListView l1 = (ListView) findViewById(R.id.list);
l1.setAdapter(new EfficientAdapter(this));
}
That's done with the help of AsyncTask (an intelligent backround thread) and ProgressDialog
When the AsyncTask starts we raise a progressdialog with indeterminate state, once the task is finished we dismiss the dialog.
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();
}
}