Android:“BadTokenException:无法添加窗口;你的活动在运行吗?

时间:2013-10-17 05:29:57

标签: java android android-asynctask android-progressbar

我在 doInBackground方法中打开progressdialog AsyncTask ,问题是从数据库加载,问题成功加载后,进度对话框将关闭< / p>

但我的问题是有一段时间我遇到错误

      android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRoot$W@44757528 is not valid; is your activity running?
通过做一些谷歌搜索我发现可能有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).

因此,如果在解除对话框之前销毁活动,我会在下面放置代码以解除progressdialog

    protected void onDestroy() {
      if (pdForNewQuestion != null)
            pdForNewQuestion.dismiss();
      super.onDestroy();

    }

但我仍然面临这个问题。我并没有破坏任何活动,但有时仍会突然出现错误,有时它会正常运行

异步代码在

之下
      // 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();

}

4 个答案:

答案 0 :(得分:1)

如果对话框显示,则检查对话框是否显示,然后仅解除此对象..

@Override
protected void onDestroy() {
    if (pdForNewQuestion != null) {
        if (pdForNewQuestion.isShowing()) {
            pdForNewQuestion.dismiss();
            pdForNewQuestion = null;
        }
    }
    super.onDestroy();
}

答案 1 :(得分:0)

你在新线程中运行无限循环,但没有破坏循环并停止该线程。即使活动变为背景,它也会在后台无限运行。一旦工作完成,请尝试停止线程。

答案 2 :(得分:0)

首先,为什么要在AsyncTask内开始Thread?据我所知,你试图每隔60秒开始AsyncTask并填写一个新问题。仅使用HandlerAsyncTask来实现此目的的方法要好得多。

创建Handler并发布Runnable,每隔几秒运行一次,根据结果开始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);

您可以像这样创建AsyncTask

    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();
        }
    }

}

答案 3 :(得分:0)

这通常是由于您的应用尝试使用先前完成的“活动”作为上下文来显示对话框。然后在显示对话框之前,检查活动是否被其他一些应用程序或其他触发器未关闭

if (!isFinishing()) {
    //showdialog here
    }