从多个活动中调用共享首选项,并访问其中一个活动中的按钮

时间:2012-04-27 04:10:08

标签: android sharedpreferences android-preferences

我正在尝试实现从两个不同的活动中调用的共享首选项。其中一个首选项是一个隐藏或公开其中一个活动的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是在不同的Activity的xml布局文件中定义的。正如您所料,在尝试访问btnClear时,我在共享首选项更改的代码中获得了空指针异常。但奇怪的是,关于它的其他一切工作正常(?!)。也就是说,当我重新启动应用程序时,首选项复选框已更改,并且已执行相应的代码。

实际问题是:如何设置首选项代码以支持能够从两个不同的活动中调用首选项以及更改其中一个变量的简单目标?非常感谢。

编辑>>按照Raju的要求,这里是logcat:

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'

1 个答案:

答案 0 :(得分:2)

  

实际问题是:如何设置首选项代码以支持   能够从两个不同的地方调用偏好的简单目标   活动,并改变其中一个变量?非常感谢。

如果我正确解释了您的问题(并提供了代码段),就好像您正在尝试将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的{​​{1}}内,但是如果您需要重新评估Activity中可能已创建且位于堆栈上的可见性,你可以简单地将其移动到例如onResume()