在自定义Preference时需要使用一个完全不同的布局,在使用的过程中遇到一个问题,就是数据刷新不了.找到很长时间,现在总结一下原因,以便后续犯了类似的错误.

上面图中的红色部分就是我想要的效果的未完成的样子,本意是想传递4个float 类型的数字后,可以把手机存储的使用情况显示出来.
但是发现数据也已经传递成功了,对应的textview 打印的值也是期望的xxGB ,但是实际显示的确实错误的.
下面贴上主要的源码:
DoovInternalStorageItemPreference.java 是自定义的Preference
public class DoovInternalStorageItemPreference extends Preference {private final String TAG = DoovInternalStorageItemPreference.class.getSimpleName();private TextView mTotalSpace ;private TextView mOthersSpace ;private TextView mUsedSpace ;private TextView mAvaliableSpace ;private float total;private float others;private float used;private float avaliable;public DoovInternalStorageItemPreference(Context context,AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr,0);}public DoovInternalStorageItemPreference(Context context, AttributeSet attrs) {this(context, attrs,0);}public DoovInternalStorageItemPreference(Context context) {this(context,null);}public DoovInternalStorageItemPreference(Context context,AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);setLayoutResource(R.layout.doov_preference_internal_stroge);Log.d(TAG,"DoovInternalStorageItemPreference mTotalSpace=" + mTotalSpace);}@Overrideprotected View onCreateView(ViewGroup parent) {View view = super.onCreateView(parent);Log.d(TAG,"onCreateView=" + mTotalSpace);return view;}@Overrideprotected void onBindView(View view) {super.onBindView(view);mTotalSpace = (TextView)view.findViewById(R.id.total_storage);mOthersSpace = (TextView)view.findViewById(R.id.others_storage);mUsedSpace = (TextView)view.findViewById(R.id.used_storage);mAvaliableSpace = (TextView)view.findViewById(R.id.available_storage);Log.d(TAG,"onBindView=" + mTotalSpace);}public void setData(float total,float other,float used,float avaliable){this.total = (float)(Math.round(total*100))/100;//保留2个小数点this.others = (float)(Math.round(other*100))/100;//保留2个小数点this.used = (float)(Math.round(used*100))/100;//保留2个小数点this.avaliable = (float)(Math.round(avaliable*100))/100;//保留2个小数点Log.d(TAG,"total=" + mTotalSpace.getText().toString() +"others=" + others + "other=" + other);//errormTotalSpace.setText(getContext().getString(R.string.memoryusage_item_total_space, this.total));mOthersSpace.setText(getContext().getString(R.string.memoryusage_item_available_space, this.others));mUsedSpace.setText(getContext().getString(R.string.memoryusage_item_used_space, this.used));mAvaliableSpace.setText(getContext().getString(R.string.memoryusage_item_other_space, this.avaliable));notifyChanged();/*//okmTotalSpace.setText(getContext().getString(R.string.memoryusage_item_total_space, total));mOthersSpace.setText(getContext().getString(R.string.memoryusage_item_available_space, other));mUsedSpace.setText(getContext().getString(R.string.memoryusage_item_used_space, used));mAvaliableSpace.setText(getContext().getString(R.string.memoryusage_item_other_space, avaliable));*/}}
光键就是上面的这个自定义的Preference.它的setData 中有2种写法,一种是带notifyChange(),另外一种不是.第一种是错误的.第2种是错误的.
原因就是调用notifyChange() 之后会导致DoovInternalStorageItemPreference 的onCreateView() 和onBindView()重新执行.也就相当于layout被重新加载了.所以手机显示的值就是配置的xml 里面的默认的字符.
去掉notifyChange() 就恢复正常了.
其实这样还是有其他问题.继续看调用setData() 的地方
public class DoovPreferenceActivity extends PreferenceActivity {private DoovInternalStorageItemPreference mpreference ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);addPreferencesFromResource(R.xml.test_preferencescreen);mpreference = new DoovInternalStorageItemPreference(this.getApplicationContext());//mpreference.setData(7, 8, 9, 10);getPreferenceScreen().addPreference(mpreference);}@Overrideprotected void onResume() {super.onResume();new Handler().postDelayed(new Runnable() {@Overridepublic void run() {mpreference.setData(17, 18, 19, 20);}}, 200);//mpreference.setData(17, 18, 19, 20);}}
在onResume 里面有2个调用setData() 的方法的地方.在上面代码的前提下,第2个是会报错的.但是第一种方法有不常用,怎么办?
所以正确的写法是应该在setData() 里面只记录下相关float 类型的值,将TextView 相关的数据更新操作放在Preference 的onBindView() 里面去.
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/total_storage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dip"android:layout_marginTop="10dip"android:layout_alignParentTop="true"android:layout_alignParentLeft="true"android:text="@string/memoryusage_item_total_space"android:textColor="#999999"android:textSize="14sp" /><TextViewandroid:id="@+id/others_storage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dip"android:layout_alignParentTop="true"android:layout_toRightOf="@id/total_storage"android:layout_alignLeft="@+id/available_storage"android:text="@string/memoryusage_item_other_space"android:textColor="#999999"android:textSize="14sp" /><TextViewandroid:id="@+id/available_storage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="32dip"android:layout_marginTop="10dip"android:layout_marginBottom="10dip"android:layout_toRightOf="@+id/used_storage"android:layout_below="@+id/others_storage"android:text="@string/memoryusage_item_available_space"android:textColor="#999999"android:textSize="14sp" /><TextViewandroid:id="@+id/used_storage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dip"android:layout_marginTop="10dip"android:layout_marginBottom="10dip"android:layout_alignParentLeft="true"android:layout_below="@id/total_storage"android:text="@string/memoryusage_item_used_space"android:textColor="#999999"android:textSize="14sp" /></RelativeLayout>
本文探讨了在自定义Preference时遇到的数据无法正确刷新的问题。通过对比两种setData方法的实现,发现notifyChanged()的不当使用导致了布局的重新加载,进而使数据显示异常。最终提出了将数据更新逻辑移至onBindView内的解决方案。
5398

被折叠的 条评论
为什么被折叠?



