Android 安卓系统:;BadTokenException:无法添加窗口;您的活动正在进行吗?”;在PreferenceActivity中显示对话框时

Android 安卓系统:;BadTokenException:无法添加窗口;您的活动正在进行吗?”;在PreferenceActivity中显示对话框时,android,progressdialog,preferenceactivity,Android,Progressdialog,Preferenceactivity,我想寻求一些帮助:在我的应用程序中,我只有一个活动,一个首选活动(不需要其他活动,它只是一个简单的后台同步应用程序,所以首选活动是主/启动器)。在用户设置首选项后,检查复选框首选项,并启动(或停止)服务。开始时,将显示一个对话框。 但问题是:如果用户按back(离开活动),再次启动它,然后尝试检查checkBoxPref,则prefsactivity会崩溃。对话框不显示。我不知道为什么,以及如何修复它 此代码与该部分完全相同,是什么导致了问题: PrefsActivity.java: pa

我想寻求一些帮助:在我的应用程序中,我只有一个活动,一个
首选活动
(不需要其他活动,它只是一个简单的后台同步应用程序,所以
首选活动
是主/启动器)。在用户设置首选项后,检查
复选框首选项
,并启动(或停止)服务。开始时,将显示一个对话框。 但问题是:如果用户按back(离开活动),再次启动它,然后尝试检查
checkBoxPref
,则
prefsactivity
会崩溃。对话框不显示。我不知道为什么,以及如何修复它

此代码与该部分完全相同,是什么导致了问题:

PrefsActivity.java:

   package is.it.works;

   // imports .....

   public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
SharedPreferences prefs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    prefs.registerOnSharedPreferenceChangeListener(this);
}// onCreate

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        showDialog(1);
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case 1: {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("press back twice, start the app again, and click checkbox...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                prefs.edit().putBoolean("cancel", false).commit();
            }
        });
        return dialog;
    }// case
    }// switch
    return null;
}// onCreateDialog
}// PrefsActivity
prefs.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference android:key="checkTest" android:title="test" />

</PreferenceScreen>
在谷歌搜索了很多之后,我认为错误的部分是
ProgressDialog=newprogressdialog(这个)。原因
更改。但将其更改为
getApplicationContext()
,或
PrefsActivity。这没有帮助,问题仍然存在。
请告诉我为什么会发生这种情况,解决办法是什么!非常感谢。

我被卡住了,现在我不知道……

也许你没有关闭或注销活动中的某些内容。在这种情况下,请尝试在onDestroy上注销broadcastreceiver

我遇到了一个非常类似的问题(这让我来到这里),并找到了一个非常简单的解决方法。虽然我的代码不同,但它应该很容易适应。以下是我的解决方案:

public void showBox() {
    mActive = true;
    if (! ((Activity) mContext).isFinishing()) {
        mDialogBox.show();
    }
} 
因此,在问题中的示例代码中,修复可能是(猜测):


在将崩溃跟踪引入一个项目后,我注意到这个问题经常出现,并发现在整个项目中使用相同的修复程序来消除崩溃:

  • 切勿将对话框声明/实例化为局部变量
  • 使所有对话框成为活动的实例变量
  • 重写onDestroy并调用if(dialog!=null)dialog.disease()
例如:

MyActivity extends Activity {
  ProgressDialog mProgressDialog;
  AlertDialog mAlertDialog;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    mProgressDialog = new ProgressDialog(MyActivity.this);
    mAlertDialog = new AlertDialog.Builder(MyActivity.this).show();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if(mProgressDialog != null) {
      mProgressDialog.dismiss();
    }
    if(mAlertDialog != null) {
      mAlertDialog.dismiss();
    }
  }

错误消息说“无法添加窗口”是误导性的,因为我发现错误发生在您离开活动时,并且传递给对话框的上下文已失效。

顶级解决方案只能防止崩溃。对我来说,问题是我引用了错误的
上下文来显示警报对话框。通过正确的
上下文后,问题就解决了。

对我来说,这解决了问题。。检查对话框是否为空或未显示,如果是,则再次创建

    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 

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

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

使用getParent()代替此链接,并尝试检查此链接[BadTokenException]()。这对你有帮助。谢谢Venky。使用getParent()会给我NullpointerException:(感谢您的回答,我也找到了这个页面。但在活动未完成时显示对话框不是解决方案。在按下“上一步”并重新开始后,活动处于运行状态。问题应该是(我认为)活动“更改”(更改了“此”参考),并不是说它正在完成。@Lama在您从该引用更改后,它现在工作了吗?您不应该将一个布尔值与另一个布尔值进行比较,而应该使用布尔值
运算符(或不使用任何运算符)相反。是风格问题,而不是功能问题。两者在技术上是相同的,但是:后者有一个我喜欢的答案:它更容易阅读,就像在
中一样!
读起来不是,Java标识符通常是英文可读的。感谢Darkhogg的链接。提出了一些好的观点。上面的答案示例已被更改,我还将介绍e正在更改我的代码样式。此转换为
Activity
是多余的。@对于第一个示例代码,
Activity
转换是必需的,因为
mContext
作为
Context
对象传递。但是,我认为第二个代码示例的转换是正确的,因此我将其删除。是否确实需要取消此转换你自己的e对话框?android的活动代码似乎已经为你关闭了它们:是的,这似乎是正确的。我通常使用由片段组成的代码库,所以我猜我在8月份写这篇文章时是指片段。我会研究它并更新这篇文章。正确的上下文是什么?应用程序上下文?
MyActivity extends Activity {
  ProgressDialog mProgressDialog;
  AlertDialog mAlertDialog;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    mProgressDialog = new ProgressDialog(MyActivity.this);
    mAlertDialog = new AlertDialog.Builder(MyActivity.this).show();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if(mProgressDialog != null) {
      mProgressDialog.dismiss();
    }
    if(mAlertDialog != null) {
      mAlertDialog.dismiss();
    }
  }
    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 
if (!isFinishing()) {
    //showdialog here
    }