【问题标题】:Android: “BadTokenException: Unable to add window; is your activity running?Android:“BadTokenException:无法添加窗口;您的活动正在运行吗?
【发布时间】:2013-10-17 05:29:57
【问题描述】:

我在 doInBackground 方法中使用 AsyncTask 打开progressdialog,问题正在从数据库加载,问题成功加载后,进度对话框将关闭

但我的问题是有时我会出现以下错误

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

}

【问题讨论】:

  • 发布你的异步任务代码,我猜你还没有关闭你的进度对话框。
  • @Kinjal 请发布您的asynctask 代码
  • @Kinjal 您在旋转手机时是否遇到错误或通常会出现错误?
  • 不是在旋转的时候,但是在运行我的活动时会自动出现错误,它可能是某个时间或不同的时间:(

标签: java android android-asynctask android-progressbar


【解决方案1】:

如果对话框正在显示,则检查对话框是否正在显示,然后只像这样关闭..

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

【讨论】:

  • Kalyan pvs 感谢您的建议,但错误仍然存​​在 :(
【解决方案2】:

您正在新线程内运行无限循环,但没有中断循环并停止该线程。即使活动进入后台,它也会在后台无限运行。工作完成后尝试停止线程。

【讨论】:

    【解决方案3】:

    首先,您为什么要在Thread 中开始您的AsyncTask?据我了解,您正尝试每 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();
            }
        }
    
    }
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2015-05-27
        • 1970-01-01
        • 2011-11-16
        • 1970-01-01
        • 2017-05-31
        • 2019-01-03
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        相关资源
        最近更新 更多