android自定义更新,Android 完美解决自定义preference与ActivityGroup UI更新的问题

之前发过一篇有关于自定义preference 在ActivityGroup 的包容下出现UI不能更新的问题,当时还以为是Android 的一个BUG 现在想想真可笑 。其实是自己对机制的理解不够深刻,看来以后要多看看源码才行。

本篇讲述内容大致为如何自定义preference 开始到与ActivityGroup 互用下UI更新的解决方法。

首先从扩展preference开始:

类文件必须继承自Preference并实现构造函数,这里我一般实现两个构造函数分别如下(类名为:test):

publictest(Context context) {this(context,null);//TODO Auto-generated constructor stub}publictest(Context context, AttributeSet attrs) {

super(context, attrs);//TODO Auto-generated constructor stub}

这里第二个构造函数第二个参数为可以使用attrs 为我们自定义的preference 添加扩展的注册属性,比如我们如果希望为扩展的preference 添加一个数组引用,就可使用如下代码:

intresouceId=attrs.getAttributeResourceValue(null,"Entries",0);if(resouceId>0) {

mEntries=getContext().getResources().getTextArray(resouceId);

}

这里的mEntries 是头部声明的一个数组,我们可以在xml文件通过 Entries=数组索引得到一个数组。在这里不深入为大家示范了。

我们扩展preference 有时想让其UI更丰富更好看,这里我们可以通过引用一个layout 文件为其指定UI,可以通过实现如下两个回调函数:

@OverrideprotectedView onCreateView(ViewGroup parent) {//TODO Auto-generated method stubreturnLayoutInflater.from(getContext()).inflate(

R.layout.preference_screen, parent,false);

}

此回调函数与onBindView 一一对应,并优先执行于onBindView ,当创建完后将得到的VIEW返回出去给onBindView处理,如下代码:

@OverrideprotectedvoidonBindView(View view) {//TODO Auto-generated method stubsuper.onBindView(view);

canlendar=Calendar.getInstance();

layout=(RelativeLayout) view.findViewById(R.id.area);

title=(TextView) view.findViewById(R.id.title);

summary=(TextView) view.findViewById(R.id.summary);

layout.setOnClickListener(this);

title.setText(getTitle());

summary.setText(getPersistedString(canlendar.get(Calendar.YEAR)+"/"+(canlendar.get(Calendar.MONTH)+1)+"/"+canlendar.get(Calendar.DAY_OF_MONTH)));

}

Tip:onBindView 不是必须的,可以将onBindView 里的处理代码在onCreateView 回调函数一并完成然后返回给onBindView ,具体怎么写看自己的代码风格吧。我个人比较喜欢这种写法,比较明了。

下面我们来了解一下我扩展preference 比较常用到的几个方法:

Preference another)

与另外一个preference比较,如果相等则返回0,不相等则返回小于0的数字。

Object newValue)

如果你希望你扩展的Preference 可以支持当数值改变时候可以调用OnPreferenceChangeListener此监听方法,则必须调用此方法,查看该方法源码为:

protectedboolean callChangeListener(Object newValue) {returnmOnChangeListener==null?true: mOnChangeListener.onPreferenceChange(this, newValue);

}

源码简单不做过多介绍,只是实现一个接口。

protectedboolean getPersistedBoolean(boolean defaultReturnValue) {if(!shouldPersist()) {returndefaultReturnValue;

}returnmPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);

}如果你有接触过sharePreference 相信一眼就能看出这里它为我们做了什么。

如上,获取一个String 数值

protectedboolean persistBoolean(boolean value) {if(shouldPersist()) {if(value==getPersistedBoolean(!value)) {//It's already there, so the same as persistingreturntrue;

}

SharedPreferences.Editor editor=mPreferenceManager.getEditor();

editor.putBoolean(mKey, value);

tryCommit(editor);returntrue;

}returnfalse;

}

都是sharePreference 的知识,这里不做过多介绍。其他的跟上面的都 一样,略过。

通过如上的一些设置,一个基本的扩展preference 就己经完成,下面来讲讲如果在ActivityGroup 里面让扩展的preference可以更新UI。之前 农民伯伯 探讨过,他建议我使用onContentChanged()方法,可以使UI更新 ,试了一下发现有些许问题,不过非常感谢农民伯伯。这个方法是全局刷新,则全部UI都刷新一次,但是这样不是很合理,我想了一下,那既然此方法可以更新UI那么一定可以行得通,我查看一下源码,下面把源码贴出来:

@OverridepublicvoidonContentChanged() {

super.onContentChanged();

postBindPreferences();

}/**

* Posts a message to bind the preferences to the list view.

* Binding late is preferred as any custom preference types created in

* {@link #onCreate(Bundle)} are able to have their views recycled.*/privatevoidpostBindPreferences() {if(mHandler.hasMessages(MSG_BIND_PREFERENCES))return;

mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();

}privatevoidbindPreferences() {

final PreferenceScreen preferenceScreen=getPreferenceScreen();if(preferenceScreen!=null) {

preferenceScreen.bind(getListView());

}

}

privatestaticfinalintMSG_BIND_PREFERENCES=0;privateHandler mHandler=newHandler() {

@OverridepublicvoidhandleMessage(Message msg) {switch(msg.what) {caseMSG_BIND_PREFERENCES:

bindPreferences();break;

}

}

};

原来,这里它是另开一条线程来更新UI,然后当值发生变化时为其发送消息,在消息队列里面处理UI,只不过它这里继承了listActivity 更新了一整个listView ,那么我们就将它提取出来,只更新我们想要的UI则可。OK,思路出来了,下面将我扩展的一个preference 的源码提供出来:

package com.yaomei.preference;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import android.app.Dialog;

import android.content.Context;

import android.content.DialogInterface;

import android.os.Handler;

import android.os.Message;

import android.preference.Preference;

import android.preference.PreferenceGroup;

import android.util.AttributeSet;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.view.View.OnClickListener;

import android.widget.AdapterView;

import android.widget.ListView;

import android.widget.RelativeLayout;

import android.widget.SimpleAdapter;

import android.widget.TextView;

import android.widget.AdapterView.OnItemClickListener;

import com.yaomei.set.R;publicclassPreferenceScreenExt extends PreferenceGroup implements

OnItemClickListener, DialogInterface.OnDismissListener {privateDialog dialog;privateTextView title, summary;privateRelativeLayout area;privateListView listView;

Listlist;privateList>listStr;privateCharSequence[] mEntries;privateString mValue;privateSimpleAdapter simple;privatestaticfinalintMSG_BIND_PREFERENCES=0;privateHandler mHandler=newHandler() {

@OverridepublicvoidhandleMessage(Message msg) {switch(msg.what) {caseMSG_BIND_PREFERENCES:

setValue(mValue);break;

}

}

};publicPreferenceScreenExt(Context context, AttributeSet attrs) {this(context, attrs, android.R.attr.preferenceScreenStyle);//TODO Auto-generated constructor stub}publicPreferenceScreenExt(Context context, AttributeSet attrs,intdefStyle) {

super(context, attrs, android.R.attr.preferenceScreenStyle);//TODO Auto-generated constructor stubintresouceId=attrs.getAttributeResourceValue(null,"Entries",0);if(resouceId>0) {

mEntries=getContext().getResources().getTextArray(resouceId);

}

}

@OverrideprotectedvoidonBindView(View view) {//TODO Auto-generated method stubarea=(RelativeLayout) view.findViewById(R.id.area);

title=(TextView) view.findViewById(R.id.title);

summary=(TextView) view.findViewById(R.id.summary);

title.setText(getTitle());

summary.setText(getPersistedString(getSummary().toString()));

area.setOnClickListener(newOnClickListener() {

@OverridepublicvoidonClick(View v) {//TODO Auto-generated method stubshowDialog();

}

});

}

@OverrideprotectedView onCreateView(ViewGroup parent) {//TODO Auto-generated method stuView view=LayoutInflater.from(getContext()).inflate(

R.layout.preference_screen, parent,false);returnview;

}publicvoidbindView(ListView listview) {intlength=mEntries.length;inti=0;

listStr=newArrayList>();for(i=0; i

HashMapmap=newHashMap();

map.put("keyname", mEntries[i].toString());

listStr.add(map);

}

simple=newSimpleAdapter(getContext(), listStr, R.layout.dialog_view,newString[] {"keyname"},newint[] { R.id.text });

listview.setAdapter(simple);

listview.setOnItemClickListener(this);

}publicvoidshowDialog() {

listView=newListView(getContext());

bindView(listView);

dialog=newDialog(getContext(), android.R.style.Theme_NoTitleBar);

dialog.setContentView(listView);

dialog.setOnDismissListener(this);

dialog.show();

}

@OverridepublicvoidonItemClick(AdapterView>parent, View view,intposition,longid) {//TODO Auto-generated method stubmValue=listStr.get(position).get("keyname").toString();

persistString(mValue);

callChangeListener(mValue);

dialog.dismiss();

}

@OverridepublicvoidonDismiss(DialogInterface dialog) {//TODO Auto-generated method stub}privateOnPreferenceChangeListener temp;publicinterfaceOnPreferenceChangeListener {publicboolean onPreferenceChange(Preference preference, Object newValue);

}publicvoidsetOnPreferenceChangeListener(

OnPreferenceChangeListener preference) {this.temp=preference;

}publicvoidsetValue(String value) {

summary.setText(value);

}publicboolean callChangeListener(Object newValue) {returntemp==null?true: temp.onPreferenceChange(this, newValue);

}publicvoidpostBindPreferences() {if(mHandler.hasMessages(MSG_BIND_PREFERENCES))return;

mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();

}

}

然后在preferenceActivity 界面在回调函数:onPreferenceChange调用postBindPreferences即可更新。

Tip:这里的onPreferenceChange  调用postBindPreferences 不是必须的,你同样可以在内部里面实现,通过执行某一操作发送消息也可。

好了,在这里我要感谢那几位朋友对我的帮助,提出了很多宝贵的意见。谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值