Вызов общих настроек из нескольких действий и доступ к кнопке в одном из них

Я пытаюсь реализовать общие настройки для вызова из двух разных действий. Одним из параметров является флажок, который скрывает или показывает кнопку, содержащуюся в файле макета xml одного из действий.

Этот сценарий реализуется с помощью:

public class MyPreferencesActivity extends PreferenceActivity
    implements OnSharedPreferenceChangeListener { ... }

Также в классе MyPreferencesActivity у меня есть код изменения предпочтений следующим образом:

@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    Button btnClear = (Button) findViewById(R.id.clearbuttonid);
    if (prefs.getBoolean("Clear User Flag", true))
        btnClear.setVisibility(View.VISIBLE);
    else
        btnClear.setVisibility(View.INVISIBLE);
}

Класс предпочтений также имеет:

@Override     
protected void onResume() {
    super.onResume();
    getPreferenceScreen().getSharedPreferences().
        registerOnSharedPreferenceChangeListener(this);     
}

... с onPause() аналогичным образом отменяет регистрацию слушателя.

Как написано, я не совсем ожидал, что этот код будет работать, потому что clearbuttonid определен в другом XML-файле макета Activity. И, как и следовало ожидать, я получаю исключение нулевого указателя в коде изменения общих предпочтений при попытке доступа к btnClear. Но странно то, что все остальное в нем работает корректно (?!). То есть, когда я перезапускаю приложение, флажок предпочтения был изменен, и соответствующий код был выполнен.

Практический вопрос: как мне настроить код настроек для поддержки простой цели — иметь возможность вызывать настройки из двух разных действий и изменять переменную в одном из них? Большое спасибо.

РЕДАКТИРОВАТЬ >> По запросу Раджу, вот логарифм:

04-27 00:26:57.989: I/onSharedPreferenceChange(537): Shared preference changed
04-27 00:26:57.989: D/AndroidRuntime(537): Shutting down VM
04-27 00:26:57.989: W/dalvikvm(537): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
04-27 00:26:58.029: E/AndroidRuntime(537): FATAL EXCEPTION: main
04-27 00:26:58.029: E/AndroidRuntime(537): java.lang.NullPointerException
04-27 00:26:58.029: E/AndroidRuntime(537):  at com.xyzzy.prototype.MyPreferencesActivity.onSharedPreferenceChanged(MyPreferencesActivity.java:49)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners(SharedPreferencesImpl.java:455)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.app.SharedPreferencesImpl$EditorImpl.apply(SharedPreferencesImpl.java:365)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.Preference.tryCommit(Preference.java:1339)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.Preference.persistBoolean(Preference.java:1605)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.TwoStatePreference.setChecked(TwoStatePreference.java:79)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.TwoStatePreference.onClick(TwoStatePreference.java:68)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.Preference.performClick(Preference.java:939)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:202)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.widget.AdapterView.performItemClick(AdapterView.java:292)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.widget.AbsListView.performItemClick(AbsListView.java:1058)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.widget.AbsListView$PerformClick.run(AbsListView.java:2514)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.widget.AbsListView$1.run(AbsListView.java:3168)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.os.Handler.handleCallback(Handler.java:605)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.os.Handler.dispatchMessage(Handler.java:92)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.os.Looper.loop(Looper.java:137)
04-27 00:26:58.029: E/AndroidRuntime(537):  at android.app.ActivityThread.main(ActivityThread.java:4424)
04-27 00:26:58.029: E/AndroidRuntime(537):  at java.lang.reflect.Method.invokeNative(Native Method)
04-27 00:26:58.029: E/AndroidRuntime(537):  at java.lang.reflect.Method.invoke(Method.java:511)
04-27 00:26:58.029: E/AndroidRuntime(537):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
04-27 00:26:58.029: E/AndroidRuntime(537):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
04-27 00:26:58.029: E/AndroidRuntime(537):  at dalvik.system.NativeStart.main(Native Method)
04-27 00:26:58.599: I/dalvikvm(537): threadid=3: reacting to signal 3
04-27 00:26:58.618: I/dalvikvm(537): Wrote stack traces to '/data/anr/traces.txt'

person gcl1    schedule 27.04.2012    source источник
comment
Находится ли другое действие в активном состоянии, когда вызывается onsharedpreferencechanged?   -  person 5hssba    schedule 27.04.2012


Ответы (1)


Практический вопрос: как мне настроить код настроек для поддержки простой цели — иметь возможность вызывать настройки из двух разных действий и изменять переменную в одном из них? Большое спасибо.

Если я правильно интерпретировал ваш вопрос (и предоставил фрагменты кода), кажется, что вы пытаетесь «протолкнуть» изменения, сделанные из PreferenceActivity, в другие (потенциально запущенные?) действия. Если это действительно так, у вас, вероятно, все наоборот. Вместо того, чтобы пытаться протолкнуть изменения предпочтений, вы должны «извлекать» их значения из действий.

Другими словами, не пишите код, как сейчас:

if (prefs.getBoolean("Clear User Flag", true))
    btnClear.setVisibility(View.VISIBLE);
else
    btnClear.setVisibility(View.INVISIBLE);

Как вы правильно сказали (и опытным путем установлено), вы не можете получить доступ к виджетам в макете, который не является частью текущего Activity, будь то «обычный» или PreferenceActivity. Вы должны рассматривать настройки как центральную среду для постоянного хранения данных и состояния вашего приложения. Прелесть в том, что вы можете получить доступ к настройкам из любого места, если у вас есть ссылка Context.

Таким образом, вместо того, чтобы пытаться отправить изменение, как описано выше, все, что вам нужно сделать в PreferenceActivity, — это убедиться, что изменение сохранено. Сделав это, вы можете просто переключить видимость btnClear внутри Activity (или Fragment), которому он принадлежит, запросив сохраненное значение из настроек:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean visible = prefs.getBoolean("Clear User Flag", true)
btnClear.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);

Вы можете поместить это, например, в onCreate(...) вашего Activity, но если вам нужно переоценить видимость в Activity, который может быть уже создан и находится в стеке, вы можете просто переместить его, например. onResume().

person MH.    schedule 27.04.2012
comment
Исправлено! Спасибо, что разъяснили это для меня. Я ценю ваше внимательное прочтение проблемы и четкое объяснение. - person gcl1; 27.04.2012