2015-02-10 57 views
1

以下代码片段显示了一个片段,其中显示了一些首选项,包括自定义首选项(ColorPickerPreference)。自定义首选项以ClassCastException结尾

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:不能投字符串为int。 我不明白我做错了什么,但如果我排除自定义首选项ColorPickerPreference一切工作正常?

下面是完整的堆栈跟踪:

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) 
+1

发布完整的错误消息。 – Simas 2015-02-10 14:31:35

+0

除此之外,发布完整的堆栈跟踪。 – CommonsWare 2015-02-10 14:32:51

+0

我认为在XML中设置的默认值始终是字符串。你喜欢的东西使用整数。不知道如何解决这个问题。 – njzk2 2015-02-10 14:39:16

回答

0

问题解决了: 之前我使用的自定义偏好ColorPickerPreference我用PreferenceList具有相同的优先键。这个PreferenceList将初始值保存为一个字符串,所以我的新偏好试图将一些“旧”字符串值转换为一个整数,在这种情况下这是不可能的。我只是改变了新的偏好的关键。

但是,是否可以删除SharedPreferences中的值,因此可以避免这样的错误?

+0

http://stackoverflow.com/questions/3687315/deleting-shared-preferences – 2015-05-30 01:45:40

1

对于那些谁遇到这个错误没有重复键,下面的解决方案可以帮助:

尝试重新安装应用程序。您在开发过程中有意改变了偏好值的类别,导致旧值与不兼容类型保持存储在一起,从而阻止设置进行比较并更改为新值。

通过卸载已连接(或模拟)设备上的应用程序,首选项也应该被删除。然后,密钥可以被新的值类型自由使用。

如果不是这种情况,请检查您的自定义首选项类。当您将该值另存为另一种类型而不是您尝试加载它的类型时,您也可以获得类转换例外。

所以说:在他们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类型作为示例,但它应该以与其他持久方法相同的方式工作。