由于当前不支持 MODE_MULTI_PROCESS,除了解决它之外,我还没有找到任何方法来处理进程之间的共享首选项。
我知道人们正在共享他们为解决此问题而编写的库,但我实际上使用了我在 another thread 上找到的第三方库,它实现了 SQLLite 来代替共享首选项:
https://github.com/hamsterready/dbpreferences
但是,对我来说重要的是我在其他解决方案中没有找到解决方案,即维护已内置在 Preference Fragment 中的自动 UI 生成 - 最好能够在 XML 中指定您的元素并调用 addPreferencesFromResource(R.xml.偏好)而不是必须从头开始构建您的 UI。
因此,为了完成这项工作,我将所需的每个 Preference 元素(在我的例子中只是 Preference、SwitchPreference 和 EditTextPreference)子类化,并覆盖了基类中的一些方法,以包括保存到 DatabaseSharedPreferences 的实例来自上述库。
例如,下面我将 EditTextPreference 子类化并从基类中获取首选项键。然后我覆盖 Preference 基类中的 persist 和 getPersisted 方法。然后我在 EditText 基类中覆盖 onSetInitialValue、setText 和 getText。
public class EditTextDBPreference extends EditTextPreference {
private DatabaseBasedSharedPreferences mDBPrefs;
private String mKey;
private String mText;
public EditTextDBPreference(Context context) {
super(context);
init(context);
}
public EditTextDBPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public EditTextDBPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EditTextDBPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context)
{
mDBPrefs = new DatabaseBasedSharedPreferences(context);
mKey = super.getKey();
}
public DatabaseBasedSharedPreferences getSharedDBPreferences()
{
if (mDBPrefs == null) {
return null;
}
return mDBPrefs;
}
@Override
protected boolean persistBoolean(boolean value) {
if (mKey != null)
mDBPrefs.putBoolean(mKey,value);
return super.persistBoolean(value);
}
@Override
protected boolean persistFloat(float value) {
if (mKey != null)
mDBPrefs.putFloat(mKey, value);
return super.persistFloat(value);
}
@Override
protected boolean persistInt(int value) {
if (mKey != null)
mDBPrefs.putInt(mKey, value);
return super.persistInt(value);
}
@Override
protected boolean persistLong(long value) {
if (mKey != null)
mDBPrefs.putLong(mKey, value);
return super.persistLong(value);
}
@Override
protected boolean persistString(String value) {
if (mKey != null)
mDBPrefs.putString(mKey, value);
return super.persistString(value);
}
@Override
protected boolean getPersistedBoolean(boolean defaultReturnValue) {
if (mKey == null)
return false;
return mDBPrefs.getBoolean(mKey, defaultReturnValue);
}
@Override
protected float getPersistedFloat(float defaultReturnValue) {
if (mKey == null)
return -1f;
return mDBPrefs.getFloat(mKey, defaultReturnValue);
}
@Override
protected int getPersistedInt(int defaultReturnValue) {
if (mKey == null)
return -1;
return mDBPrefs.getInt(mKey, defaultReturnValue);
}
@Override
protected long getPersistedLong(long defaultReturnValue) {
if (mKey == null)
return (long)-1.0;
return mDBPrefs.getLong(mKey, defaultReturnValue);
}
@Override
protected String getPersistedString(String defaultReturnValue) {
if (mKey == null)
return null;
return mDBPrefs.getString(mKey, defaultReturnValue);
}
@Override
public void setKey(String key) {
super.setKey(key);
mKey = key;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setText(restoreValue ? getPersistedString(mText) : (String) defaultValue);
}
@Override
public void setText(String text) {
final boolean wasBlocking = shouldDisableDependents();
boolean textChanged = false;
if (mText != null && !mText.equals(text))
textChanged = true;
mText = text;
persistString(text);
if (textChanged) {
// NOTE: This is a an external class in my app that I use to send a broadcast to other processes that preference settings have changed
BASettingsActivity.SendSettingsUpdate(getContext());
}
final boolean isBlocking = shouldDisableDependents();
if (isBlocking != wasBlocking) {
notifyDependencyChange(isBlocking);
}
}
@Override
public String getText() {
return mText;
}
然后您只需在您的preferences.xml 文件中指定新元素,瞧!
您现在获得了 SQLLite 的进程互操作性和 PreferenceFragment 的 UI 自动生成!
<com.sampleproject.EditTextDBPreference
android:key="@string/pref_key_build_number"
android:title="@string/build_number"
android:enabled="false"
android:selectable="false"
android:persistent="false"
android:shouldDisableView="false"/>