1

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

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

public static void changeTheme(Activity activity, int theme)
{
    if (null != activity) {
        activity.finish();
        activity.startActivity(new Intent(activity, activity.getClass()));
    }
}

除了 1 个问题外,这很完美。在用户更改主题并且应用程序自行重新启动后,如果用户尝试再次选择新主题而没有先手动退出并打开应用程序,则对 AlertDialog.Builder 的调用将失败,我不确定原因。我在 logcat 中收到此错误:

android.view.WindowManager$BadTokenException: 无法添加窗口——令牌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 的调用才会失败(如果您手动关闭应用程序然后再次打开它,则不会发生这种情况)。任何想法如何解决这个问题?

4

1 回答 1

0

所以我决定只实现一个扩展的 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);
            }
        }
    }
}

希望这可能会在未来对其他人有所帮助;-)

于 2014-12-31T11:34:05.090 回答