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 不是必須的,你同樣可以在內部里面實現,通過執行某一操作發送消息也可。

好了,在這里我要感謝那幾位朋友對我的幫助,提出了很多寶貴的意見。謝謝。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396752.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396752.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396752.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vxlan 資料及其在 neutron中的應用

2019獨角獸企業重金招聘Python工程師標準>>> VXLAN 是一個新興的SDN 標準,它定義了一種新的 overlay 網絡,它主要的創造者是 VMware, Cisco 和 Arista。它被設計來消除虛擬化網絡世界中的 VLAN 數目的限制。VXLAN 本身是一個多播標準&#xf…

橫流式冷卻塔計算風量_研討丨卓展標準高效制冷機房技術之影響冷卻塔效率的幾個因素...

集中制冷用空調系統中,單臺冷卻塔的冷卻水量基本上都小于1,000m/h,且裝有淋水填料的橫流機械通風開式居多。本文將已橫流開式冷卻塔為對象,探討影響其效率的幾個因素。橫流開式冷卻塔示意圖如下所示:橫流開式冷卻塔示意圖 Fig 01說…

我是培訓出來的我怕誰

引子: 江小峰是我帶過的徒弟中跟我最久,也是最聰明的一個。 他一個高中生,沒上過大學,高中畢業后在老家賣了三年電腦,天天給人裝操作系統,有天他在網上看到某培訓機構招生簡介,一時沖動揣上三年血汗錢&…

android平臺gallery2應用分析,Android5.1圖庫Gallery2代碼分析數據加載流程

圖片數據加載流程。Gallery---->GalleryActivity------>AlbumSetPage------->AlbumPage--------->PhotoPage相冊集 照片集 某張圖片1,AlbumSetPage.javaprivate void initializeData(Bundle data) {String mediaPath data…

python開課吧1980課程_開課吧的課程怎么樣?

就那那些編程開發課來說。現在網絡上充斥著大量的編程開發課程,什么python的,java的,c的,而且名字一個比一個夸張,21天精通c,7天熟練運用java,3天掌握python核心代碼,這些課程標題簡…

專業概念

1.JDBC: java數據庫連接(JDBC)用于在java程序中實現數據庫的操作功能,它提供了執行sql語句,訪問各種數據庫的方法,并為各種不同的數據庫提供統一的操作接口,java.sql包中 包含了jdbc操作數據庫的所有類 2.…

前端解決跨域問題的8種方案

2019獨角獸企業重金招聘Python工程師標準>>> 1.同源策略如下: URL說明是否允許通信http://www.a.com/a.js http://www.a.com/b.js同一域名下允許http://www.a.com/lab/a.js http://www.a.com/script/b.js同一域名下不同文件夾允許http://www.a.com:8000/…

k歌的錄音伴奏合成技術如何實現_K歌神器,用唱吧麥克風攀登天籟高峰

自從喜歡上了手機K歌,經常會上傳一些自己的作品,起初無論音質如何都是樂在其中,可時間久了發現回放效果確實不如那榜單上的高手,究其原因想到了麥克風,網上一搜果然有各種K歌輔助工具,多番對比之下&#xf…

淺談內存開辟問題和Block內存問題

我們知道,內存分為棧,堆,塊。 棧中的內存由系統自己釋放,堆是存對象初始化的地方,塊是CPU與內存連接的緩沖器,運行速度比內存快,比CPU慢。 例如,我們NSMutableArray *array [NSMuta…

vue render函數_Vue原理解析(一):Vue到底是什么?

Vue,現在前端的當紅炸子雞,隨著熱度指數上升,實在是有必要從源碼的角度,對它功能的實現原理一窺究竟。個人覺得看源碼主要是看兩樣東西,從宏觀上來說是它的設計思想和實現原理;微觀上來說就是編程技巧&…

scrapy爬蟲-setting.py

# Obey robots.txt rulesROBOTSTXT_OBEY False  不遵從網站的robots.txt法則 # See also autothrottle settings and docsDOWNLOAD_DELAY 3  每次下載延遲3秒,防止造成網站攻擊 # Override the default request headers:DEFAULT_REQUEST_HEADERS { Accept:…

android點擊左上角劃出,使用Android中的Path和RectF在左上角右上角左下角繪制圓角...

有一個Path#addRoundRect()重載,它接受一個包含八個值的float數組,其中我們可以為四個角中的每一個指定x和y半徑.這些值為[x,y]對,從左上角開始,順時針繞其余部分.對于我們想要舍入的那些角,我們將該對的兩個值都設置為半徑值,并將它們保留為零,而不是那些.作為一個說明性示例,…

Nodejs微信開發

因為使用了Bot Framework開發了一個小功能,它目前支持了Skype\Teams\Slack等,但在國內來講,微信還是一個比較流行的軟件,所以需要接上微信 原來開發Bot的時候使用的是.Net開發的,這次我決定使用Nodejs開發一個簡單的后…

性別有什么用_為啥不讓男孩玩布娃娃?別讓你的“性別偏見”,給孩子的人生設限...

在養育孩子的過程中,父母總是會犯許多錯誤,更是有一些錯誤會直接使孩子毀掉一生,而性別偏見正是很多家長都會去犯的錯誤,對男孩和女孩有著刻板印象,也正是因為這一點使孩子的潛力和天賦被壓制。前幾天我帶著孩子去逛商…

android的時間代碼怎么寫,Android 日期和時間的使用實例詳解

Android 日期和時間的使用日期和時間的使用;1:彈出框TimePickerDialog,DatePickerDialog2:組件TimePicker,DatePickerTimePickerDialog的使用:通過點擊button顯示圖一,然后用戶可以設置時間DatePickerDialog的使用只需…

andriod studio 查看項目依賴_Intellij IDEA 中如何查看maven項目中所有jar包的依賴關系圖...

Maven 組件界面介紹如上圖標注 1 所示,為常用的 Maven 工具欄,其中最常用的有:第一個按鈕:Reimport All Maven Projects 表示根據 pom.xml 重新載入項目。一般單我們在 pom.xml 添加了依賴包或是插件的時候,發現標注 4…

Springboot 2.0.0單元測試

1. 引入spring-boot-starter-test包 1 <?xml version"1.0" encoding"UTF-8"?>2 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"3 xsi:schemaLocation"…

SPRING IN ACTION 第4版筆記-第二章-002-@ComponentScan、@Autowired的用法

一、ComponentScan 1. Configuration //說明此類是配置文件 ComponentScan //開啟掃描&#xff0c;會掃描當前類的包及其子包 public class CDPlayerConfig { } 2. ComponentScan(basePackages{"soundsystem", "video"})//掃描多個包 public class CDP…

Kurento協議

2019獨角獸企業重金招聘Python工程師標準>>> Kurento媒體服務器可以被兩種外部Kurento客戶端控制&#xff0c;如Java或JavaScript。這些客戶端使用Kuernto協議來和KMS通信。Kurento 協議是基于WebSocket協議&#xff0c;并使用了JSON-RPC V2.0 消息來提交請求和發送…

升級php7_PhpStorm 2019.3 發布,全面支持 PHP 7.4

PhpStorm 2019.3 發布了&#xff0c;這個版本主要集中在性能和質量上&#xff0c;旨在提供一個更穩定、更快的 IDE。PhpStorm 2019.3 全面支持 PHP 7.4&#xff0c;還帶來 PSR-12 代碼樣式&#xff0c;用于遠程解釋器的 WSL&#xff0c;MongoDB 支持&#xff0c;HTTP 客戶端更新…