以下代码段显示了一个片段,用于显示一些偏好设置,包括自定义偏好设置(ColorPickerPreference
)。
public static class PlayerEditFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.profile_player_edit);
...
定义首选项的xml文件如下所示:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="prof_key_player"
android:title="Player" >
<EditTextPreference
android:key="prof_key_player_name"
android:title="Name" />
<de.jhouse.agt.view.dialog.ColorPickerPreference
android:defaultValue="2130837679"
android:key="prof_key_player_color"
android:title="Color" />
<de.jhouse.agt.view.dialog.NumberPickerPreference
android:defaultValue="0"
android:key="prof_key_player_pos"
android:title="Position" />
</PreferenceCategory>
</PreferenceScreen>
自定义首选项ColorPickerPreference
,使用户可以从对话框中的预定义颜色列表中选择颜色:
public class ColorPickerPreference extends DialogPreference {
// the images to display
public static final Integer[] imageIDs = { R.drawable.player_white,
R.drawable.player_black, R.drawable.player_orange,
R.drawable.player_green, R.drawable.player_grey,
R.drawable.player_red, R.drawable.player_blue,
R.drawable.player_yellow, R.drawable.player_brown, };
private Gallery gallery;
private int value;
public ColorPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ColorPickerPreference(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected View onCreateDialogView() {
final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER;
gallery = new Gallery(getContext());
gallery.setLayoutParams(layoutParams);
gallery.setAdapter(new ImageAdapter(getContext()));
gallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
setValue(imageIDs[position]);
}
});
final FrameLayout dialogView = new FrameLayout(getContext());
dialogView.addView(gallery);
return dialogView;
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
gallery.setSelection(getValue(), true);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
setValue(gallery.getSelectedItemPosition());
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
Integer value = a.getInt(index, imageIDs[4]);
return value;
}
@Override
protected void onSetInitialValue(boolean restorePersistedValue,
Object defaultValue) {
setValue(restorePersistedValue ? getPersistedInt(imageIDs[4])
: (Integer) defaultValue);
}
public void setValue(int value) {
this.value = value;
persistInt(this.value);
}
public int getValue() {
return this.value;
}
/**
*
* @author Andy
*
*/
public static class ImageAdapter extends BaseAdapter {
private Context context;
private int itemBackground;
public ImageAdapter(Context c) {
context = c;
// sets a grey background; wraps around the images
TypedArray a = context.obtainStyledAttributes(R.styleable.MyGallery);
itemBackground = a.getResourceId(R.styleable.MyGallery_android_galleryItemBackground, 0);
a.recycle();
}
// returns the number of images
public int getCount() {
return imageIDs.length;
}
// returns the ID of an item
public Object getItem(int position) {
return position;
}
// returns the ID of an item
public long getItemId(int position) {
return position;
}
// returns an ImageView view
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(context);
imageView.setImageResource(imageIDs[position]);
imageView.setLayoutParams(new Gallery.LayoutParams(100, 100));
imageView.setBackgroundResource(itemBackground);
return imageView;
}
}
}
现在的问题是,当执行statetement addPreferencesFromResource(R.xml.profile_player_edit)
时,它会抛出ClassCastException:无法将String强制转换为int。
我无法弄清楚我做错了什么,但如果我排除了自定义偏好ColorPickerPreference一切正常?
这是完整的Stacktrace:
02-10 15:35:45.778: D/AndroidRuntime(19737): Shutting down VM
02-10 15:35:45.798: E/AndroidRuntime(19737): FATAL EXCEPTION: main
02-10 15:35:45.798: E/AndroidRuntime(19737): Process: de.jhouse.agt, PID: 19737
02-10 15:35:45.798: E/AndroidRuntime(19737): java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.SharedPreferencesImpl.getInt(SharedPreferencesImpl.java:239)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.Preference.getPersistedInt(Preference.java:1697)
02-10 15:35:45.798: E/AndroidRuntime(19737): at de.jhouse.agt.view.dialog.ColorPickerPreference.onSetInitialValue(ColorPickerPreference.java:103)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.Preference.dispatchSetInitialValue(Preference.java:1514)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.Preference.onAttachedToHierarchy(Preference.java:1309)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.PreferenceGroup.addPreference(PreferenceGroup.java:167)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.PreferenceGroup.addItemFromInflater(PreferenceGroup.java:108)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.PreferenceGroup.addItemFromInflater(PreferenceGroup.java:45)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.GenericInflater.rInflate(GenericInflater.java:488)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.GenericInflater.rInflate(GenericInflater.java:493)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.GenericInflater.inflate(GenericInflater.java:326)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.GenericInflater.inflate(GenericInflater.java:263)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.PreferenceManager.inflateFromResource(PreferenceManager.java:272)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.preference.PreferenceFragment.addPreferencesFromResource(PreferenceFragment.java:300)
02-10 15:35:45.798: E/AndroidRuntime(19737): at de.jhouse.agt.activity.ProfileEditActivity$PlayerEditFragment.onCreate(ProfileEditActivity.java:620)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.Fragment.performCreate(Fragment.java:2075)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:868)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1082)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.BackStackRecord.run(BackStackRecord.java:833)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:452)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.os.Handler.handleCallback(Handler.java:739)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.os.Handler.dispatchMessage(Handler.java:95)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.os.Looper.loop(Looper.java:145)
02-10 15:35:45.798: E/AndroidRuntime(19737): at android.app.ActivityThread.main(ActivityThread.java:5834)
02-10 15:35:45.798: E/AndroidRuntime(19737): at java.lang.reflect.Method.invoke(Native Method)
02-10 15:35:45.798: E/AndroidRuntime(19737): at java.lang.reflect.Method.invoke(Method.java:372)
02-10 15:35:45.798: E/AndroidRuntime(19737): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
02-10 15:35:45.798: E/AndroidRuntime(19737): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
答案 0 :(得分:1)
对于遇到此错误而没有重复键的用户,以下解决方案可能有所帮助:
尝试重新安装该应用。您可以在开发期间更改首选项值的类,导致具有不兼容类型的旧值保持与该键一起存储,从而阻止将设置进行比较并更改为新设置。
通过在连接(或模拟)设备上卸载应用程序,首选项也应该被删除。然后,密钥应该可以被新类型的值使用。
如果不是这种情况,请检查您的自定义偏好类。当您将值保存为另一种类型而不是您尝试加载的类型时,您也可以获得类转换异常。
所以:检查您的自定义偏好类&#39; persistInt()和getPersistedInt()调用的一致性方法:
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
persistInt(getYourInteger());
}
}
@Override
protected void onSetInitialValue(
boolean restorePersistedValue,
Object defaultValue) {
int worstCaseDefault = 0;
int value;
if(restorePersistedValue) {
if (defaultValue == null) {
value = worstCaseDefault;
} else { //The following line is critical.
try { value = getPersistedInt(Integer.parseInt(defaultValue.toString())); }
catch (Exception e) {
Log.e("YourPreference", "OnSetInitialValue: ", e);
value = worstCaseDefault;
}
}
} else {
try { value = Integer.parseInt(defaultValue.toString()); }
catch (Exception e) {
Log.e("YourPreference", "OnSetInitialValue: ", e);
value = worstCaseDefault;
}
}
}
如果这还没有解决问题,我猜这个偏好在重新安装后幸存下来了。在这种情况下,您可能想看看Stephen Kaiser对Andys自己的答案所评论的问题。
注意,我这里仅使用Integer类型作为示例,但它应该与其他持久化方法的工作方式相同。
答案 1 :(得分:0)
问题解决了: 在使用自定义首选项ColorPickerPreference之前,我使用了具有相同首选项键的PreferenceList。这个PreferenceList将初始值保存为String,所以我的新偏好尝试转换一些&#34; old&#34;将字符串值转换为Integer,在这种情况下是不可能的。我只是改变了新偏好的关键。
但是,是否可以删除SharedPreferences中的值,因此可以避免这样的错误?