Android PreferenceFragment中的对话框生成器

Android PreferenceFragment中的对话框生成器,android,dialog,listpreference,preferencefragment,Android,Dialog,Listpreference,Preferencefragment,我正在为我的应用程序创建一个设置部分。这将作为PreferenceFragment加载到导航抽屉布局中 我有一个ListPreference,我将使用它来切换应用程序主题。一旦你从listview中选择了一个主题,我会设置一个确认对话框,询问用户是否希望重新启动应用程序以应用新主题。如果是,我将使用以下命令重新启动Utils.java中定义的应用程序: public static void changeTheme(Activity activity, int theme) { if (n

我正在为我的应用程序创建一个设置部分。这将作为PreferenceFragment加载到导航抽屉布局中

我有一个ListPreference,我将使用它来切换应用程序主题。一旦你从listview中选择了一个主题,我会设置一个确认对话框,询问用户是否希望重新启动应用程序以应用新主题。如果是,我将使用以下命令重新启动Utils.java中定义的应用程序:

public static void changeTheme(Activity activity, int theme)
{
    if (null != activity) {
        activity.finish();
        activity.startActivity(new Intent(activity, activity.getClass()));
    }
}
除了一个问题外,它工作得非常完美。在用户更改主题且应用程序自行重新启动后,如果用户尝试再次选择新主题而未首先手动退出并打开应用程序,则调用AlertDialog.Builder失败,我不确定原因。我在logcat中得到这个错误:

android.view.WindowManager$BadTokenException:无法添加Windows-token android.os。BinderProxy@41eec418无效;你的活动正在进行吗

创建对话框时失败:

new AlertDialog.Builder(mContext)...
我在onCreate方法中设置了mContext=getActivity,对对话框生成器的调用在onSharedPreferenceChanged中:

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Log.e(TAG, "Preference Change!");
    Log.e(TAG, "Key: " + key);

    if (preferenceManager.contains(key)) {
        if (key.equals(PrivateGalleryConstants.KEY_THEME)) {
            final int theme = Integer.parseInt(preferenceManager.getString(key, "0"));
            Log.e(TAG, "Value: " + preferenceManager.getString(key, "0"));

            new AlertDialog.Builder(mContext)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setTitle(R.string.confirm_restart_title)
                    .setMessage(R.string.confirm_restart_message)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Utils.changeTheme(getActivity(), theme);
                        }

                    })
                    .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }

                    })
                    .show();


        }
        if (key.equals(PrivateGalleryConstants.KEY_ENABLE_SECURITY))
            Log.e(TAG, "Value: " + preferenceManager.getBoolean(key, false));
    }
}

我不明白为什么调用AlertDialog.Builder仅在应用程序自行重新启动后才会失败。如果手动关闭应用程序,然后再次打开它,则不会发生这种情况。有没有办法解决这个问题?

所以我决定只实现一个扩展的ListPreference,它处理创建确认对话框的问题,瞧,它现在工作得很好

public class ThemeListPreference extends ListPreference {

    private int mClickedDialogEntryIndex;

    private Context mContext;

    public ThemeListPreference(Context ctxt) {
        this(ctxt, null);
    }

    public ThemeListPreference(Context ctxt, AttributeSet attrs) {
        super(ctxt, attrs);

        mContext = ctxt;

        setNegativeButtonText(ctxt.getString(R.string.no));
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        if (getEntries() == null || getEntries() == null) {
            throw new IllegalStateException(
                    "ListPreference requires an entries array and an entryValues array.");
        }

        mClickedDialogEntryIndex = findIndexOfValue(getValue());
        builder.setSingleChoiceItems(getEntries(), mClickedDialogEntryIndex,
                new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int which) {
                        // Save preference and close dialog
                        mClickedDialogEntryIndex = which;

                        ThemeListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
                        dialog.dismiss();

                        new AlertDialog.Builder(mContext)
                                .setIcon(android.R.drawable.ic_dialog_alert)
                                .setTitle(R.string.confirm_restart_title)
                                .setMessage(R.string.confirm_restart_message)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                        Utils.changeTheme((Activity) mContext);
                                    }

                                })
                                .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }

                                })
                                .show();
                    }
                });

        builder.setPositiveButton(null, null);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {

        CharSequence[] mEntryValues = getEntryValues();

        if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
            String value = mEntryValues[mClickedDialogEntryIndex].toString();
            if (callChangeListener(value)) {
                setValue(value);
            }
        }
    }
}
希望这能在将来帮助别人-