Android應(yīng)用Preference相關(guān)及源碼淺析 Preference相關(guān)基礎(chǔ)概念
1 前言
(資料圖)
前一篇(點(diǎn)我閱讀前一篇《Android應(yīng)用Preference相關(guān)及源碼淺析(SharePreferences篇)》)我們討論分析使用了Android的SharePreferences,相信看過(guò)的朋友都有了自己的感悟與理解,這一篇我們繼續(xù)乘熱打鐵來(lái)說(shuō)說(shuō)SharePreferences的衍生品—-Preference組件。
其實(shí)Preference組件大家一定不陌生,因?yàn)閍ndroid系統(tǒng)的Setting應(yīng)用及我們市面上一些符合Android設(shè)計(jì)思想的應(yīng)用的設(shè)置界面一般都會(huì)用它來(lái)實(shí)現(xiàn),而且Google原生Android代碼中大量的使用了Preference組件。
簡(jiǎn)單說(shuō),Preference組件其實(shí)就是Android常見(jiàn)UI組件與SharePreferences的組合封裝實(shí)現(xiàn)。
2 Preference組件家族基礎(chǔ)
2-1 Preference相關(guān)基礎(chǔ)概念
既然要先說(shuō)說(shuō)Preference組件家族基礎(chǔ),那不得不先簡(jiǎn)單說(shuō)說(shuō)這些Preference組件間的關(guān)系,如下一張圖是基于API 22繪制的一副Preference組件繼承關(guān)系圖:
怎么樣?相比以前低版本的API來(lái)說(shuō),谷歌官方又增加了一些實(shí)用的Preference組件,不過(guò)遺憾的是這里面有些是被hide掉的,有些是在com.android.internal.preference包下的,所以這些hide和com.android.internal.preference包的preference我們應(yīng)用層是不能直接使用的。
到此你指定會(huì)說(shuō),這些組件和我們平時(shí)用的EditText等組件很類似,而我們平時(shí)用的EditText等組件顯示是依賴于Activity和Fragment的,那么這里的Preference組件是怎么顯示的呢?
答案就是Preference組件也有自己依賴顯示的框架,最常見(jiàn)的就像PreferenceActivity等,具體看代碼我們會(huì)發(fā)現(xiàn)如下:
public abstract class PreferenceActivity extends ListActivity implements PreferenceManager.OnPreferenceTreeClickListener, PreferenceFragment.OnPreferenceStartFragmentCallback {......}public abstract class PreferenceFragment extends Fragment implements PreferenceManager.OnPreferenceTreeClickListener {......}12345678
嘿嘿,明白了吧?其實(shí)Preference組件的使用及展示到Window的原理和普通EditText控件展示使用是類似的,因?yàn)镻reference組件的顯示框架PreferenceActivity及PreferenceFragment都是從基本的Activity及Fragment繼承而來(lái),只是針對(duì)Preference進(jìn)行了二次封裝而已。
到此對(duì)Preference組件已經(jīng)有一個(gè)基本的概念認(rèn)識(shí)了,接下來(lái)我們就一步一步往下看。
2-2 常用Preference相關(guān)基礎(chǔ)組件屬性說(shuō)明
我們可以發(fā)現(xiàn),Preference組件家族的控件還是比較豐富的,這里肯定不能一一介紹,所以還是代表性的說(shuō)幾個(gè)使用頻率最高作為指引就行了,其他的用到時(shí)參考相關(guān)官方API或者源碼即可。
2-2-1 獨(dú)立控件Preference
所有Preference組件的基類,類似常見(jiàn)控件的TextView,一個(gè)單純的item,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
如下是基類Preference的相關(guān)屬性介紹:
attrdescription
android:defaultValue默認(rèn)值。
android:dependency設(shè)置此元素附屬于另一個(gè)元素,依賴的可用則當(dāng)前元素也可用(enable),反之。
android:enabled設(shè)置是否可用。
android:fragment指定fragment。
android:icon指定左側(cè)的圖標(biāo)。
android:key選項(xiàng)的名稱,也是用來(lái)存儲(chǔ)時(shí)唯一的key。
android:layout給當(dāng)前元素指定一個(gè)自定義布局。
android:order偏好的順序。如果不指定,默認(rèn)的順序?qū)⒆帜浮?/p>
android:persistent是否將其值存儲(chǔ)到共享SharePreferences。
android:selectable設(shè)置是否可以選擇操作。
android:shouldDisableView當(dāng)enabled設(shè)置為false變暗,同時(shí)此屬性設(shè)置為false時(shí)disable但不變暗。
android:summary摘要,配置的簡(jiǎn)要說(shuō)明,顯示在標(biāo)題下面。
android:title選項(xiàng)的標(biāo)題,當(dāng)沒(méi)有設(shè)置summary時(shí)自動(dòng)垂直居中顯示。
android:widgetLayout控件可調(diào)小部件的布局。是為一個(gè)優(yōu)先選擇的布局,比如一個(gè)復(fù)選框選擇要指定一個(gè)自定義布局(注意:包括的只是復(fù)選框)在這里。
關(guān)于基類Preference提供的方法這里就不再詳細(xì)列出了,如需查看,具體翻墻點(diǎn)我。
2-2-2 獨(dú)立控件CheckPreference
CheckPreference類似常見(jiàn)控件的CheckBox,一個(gè)item,右側(cè)有一個(gè)CheckBox,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
如下是CheckPreference的相關(guān)屬性介紹:
attrdescription
android:disableDependentsState與android:dependency相反;B可用,則A不可用;B不可用,則A可用。
android:summaryOff選項(xiàng)未選中時(shí)顯示的摘要。
android:summaryOn選項(xiàng)被選中時(shí)顯示的摘要。
2-2-3 獨(dú)立控件EditTextPreference
EditTextPreference類似常見(jiàn)控件的EditText,一個(gè)item,點(diǎn)擊彈出一個(gè)EditText的對(duì)話框,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
該控件無(wú)自有屬性。具體不再介紹,相關(guān)方法查看官方API。
2-2-4 獨(dú)立控件ListPreference
ListPreference類似常見(jiàn)控件的ListView,一個(gè)item,點(diǎn)擊彈出一個(gè)ListView的Dialog,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
如下是ListPreference的相關(guān)屬性介紹:
attrdescription
android:entrieslist要顯示的item數(shù)組名字。
android:entryValueslist要顯示的item數(shù)組值。
2-2-5 獨(dú)立控件MultiSelectListPreference
MultiSelectListPreference類似常見(jiàn)控件的ListView,一個(gè)item,點(diǎn)擊彈出一個(gè)多選的ListView的Dialog,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
MultiSelectListPreference的相關(guān)屬性同上ListPreference。
2-2-6 獨(dú)立控件SwitchPreference
SwitchPreference類似常見(jiàn)控件的Switch,一個(gè)item,右側(cè)有一個(gè)Switch控件,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
如下是SwitchPreference的相關(guān)屬性介紹:
attrdescription
android:disableDependentsState與android:dependency相反;B可用,則A不可用;B不可用,則A可用。
android:summaryOff選項(xiàng)未選中時(shí)顯示的摘要。
android:summaryOn選項(xiàng)被選中時(shí)顯示的摘要。
android:switchTextOff關(guān)閉狀態(tài)的文字提示。
android:switchTextOn打開狀態(tài)的文字提示。
2-2-7 獨(dú)立控件RingtonePreference
RingtonePreference就是一個(gè)鈴聲選擇item,點(diǎn)擊彈出鈴聲選擇list的dialog,用于通過(guò)SharePreferences存儲(chǔ)操作的設(shè)置值,具體翻墻點(diǎn)我。
如下是RingtonePreference的相關(guān)屬性介紹:
attrdescription
android:ringtoneType鈴聲類型。ringtone/notification/alarm/all
android:showDefault選項(xiàng)中默認(rèn)的鈴聲。
android:showSilent是否顯示靜音項(xiàng)。
2-2-8 組合控件PreferenceScreen
PreferenceScreen就Preference hierarchy的root節(jié)點(diǎn),實(shí)例化他可以使用createPreferenceScreen(Context)方法;這個(gè)類可以依附于兩個(gè)地方,當(dāng)一個(gè)preferenceactivity指向他時(shí)用來(lái)作為根布局顯示偏好,當(dāng)他嵌套出現(xiàn)在另一個(gè)Preference hierarchy內(nèi)部時(shí)他會(huì)啟動(dòng)一個(gè)新的界面來(lái)顯示子項(xiàng)Preference或者設(shè)置的intent;綜上也就是說(shuō)它不僅可以作為設(shè)置界面顯示,而且還能夠啟動(dòng)activity,具體翻墻點(diǎn)我。
如下展示了作為根布局及子布局的兩種情況:
<--!>... other preferences here ...123456789101112131415
<--!>1234567
2-2-9 組合控件PreferenceCategory
PreferenceCategory類似于LinearLayout,用于組合一組可設(shè)置標(biāo)題的Preference,使布局更具備層次感,具體翻墻點(diǎn)我。
這個(gè)類也沒(méi)有啥特殊的東西介紹,詳細(xì)參考API。
到此常用的Preference組件xml屬性介紹完畢,對(duì)應(yīng)的Java方法就不再說(shuō)明了,還有就是他們的protect方法也不再詳細(xì)介紹,具體參見(jiàn)API。
2-3 新增Headers相關(guān)基礎(chǔ)組件屬性說(shuō)明
上面我們簡(jiǎn)單介紹了PreferenceScreen相關(guān)xml的屬性,這些其實(shí)是老版本的處理方式;自從Android 3.0引入Fragment之后,Preference相關(guān)的控件也有了變化。
由于PreferenceActivity在3.0開始也需要能夠處理多屏幕碎片化問(wèn)題,所以Android 3.0之前采用PreferenceScreen嵌套的方法來(lái)跳轉(zhuǎn)分類細(xì)則,而Android 3.0及之后使用了Preference Headers的方法來(lái)適配多屏幕碎片化問(wèn)題。
他的核心就是在主屏中通過(guò)headers的xml布局列出所有的主題設(shè)置項(xiàng),每個(gè)主題設(shè)置的詳細(xì)設(shè)置由各自指定的PreferenceFragment負(fù)責(zé),而各自的PreferenceFragment可以如傳統(tǒng)的PreferenceActivity 一樣布局自身的PreferenceScreen。
preference-headers就是他們的root,既然這樣,那我們就來(lái)看看Headers相關(guān)的組件及方法吧。
2-3-1 PreferenceActivity.Header相關(guān)屬性方法使用基礎(chǔ)
點(diǎn)我翻墻查看。Header繼承自O(shè)bject,實(shí)現(xiàn)了Parcelable,用來(lái)展示一個(gè)item的header。
相關(guān)屬性如下:
attrdescription
android:icon
android:breadCrumbShortTitle在fragment顯示的短標(biāo)題文字。
android:breadCrumbTitle在fragment顯示的標(biāo)題文字。
android:fragment當(dāng)選擇該頭文件時(shí),將顯示該fragment的全名稱。
android:id唯一識(shí)別id。
android:summaryitem描述信息。
android:titleitem頭名稱。
如下是一個(gè)簡(jiǎn)單展示:
...... ...... 節(jié)點(diǎn),類似extra,此處省略 -->123456
關(guān)于Header的用法下面會(huì)詳細(xì)演示,基本情況就介紹到這里。
2-4 Preference相關(guān)組件顯示操作控制API解釋
有了上面Preference組件基本概念及屬性介紹以后就相當(dāng)于我們有了磚瓦,接下來(lái)就是咋蓋房子了,也就是如何組合這些組件顯示在屏幕上,我們現(xiàn)在就來(lái)看看這些常用的操作。
2-4-1 PreferenceActivity相關(guān)屬性方法使用基礎(chǔ)
翻墻點(diǎn)我查看。PreferenceActivity繼承自ListActivity,這個(gè)類是Preference相關(guān)控件展示的基類,在Android 3.0以前推薦直接使用,3.0以后推薦和preferencefragment一起使用,所以你可以看見(jiàn)PreferenceActivity中有些方法現(xiàn)在已經(jīng)是過(guò)時(shí)的了。
首先看下PreferenceActivity加載xml目錄下的文件使用的方法,如下:
public class DemoActivity extends PreferenceActivity {@Override public void onBuildHeaders(List target) { super.onBuildHeaders(target); //當(dāng)大于等于3.0版本時(shí)推薦重寫該方法加載xml,headers+fragments模式 loadHeadersFromResource(R.xml.preference_header, target); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { //當(dāng)小于3.0版本時(shí)推薦重寫該方法加載xml,當(dāng)然大于時(shí)也可以用,只是不推薦而已 addPreferencesFromResource(R.xml.preference); } }}1234567891011121314
如下我們來(lái)看看PreferenceActivity相關(guān)的常用方法:
methoddescription
public void addPreferencesFromIntent(Intent intent)@deprecated,添加一個(gè)匹配intent的preferences activity。
public void addPreferencesFromResource(int preferencesResId)@deprecated,添加一個(gè)xml到activity。
public Preference findPreference(CharSequence key)@deprecated,查找一個(gè)指定key的Preference。
public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData)結(jié)束指定的fragment,參數(shù)返回類似activity。
public PreferenceManager getPreferenceManager()@deprecated,獲取activity使用的PreferenceManager實(shí)例。
public PreferenceScreen getPreferenceScreen()@deprecated,獲取當(dāng)前activity的根布局視圖。
public boolean hasHeaders()返回當(dāng)前activity是否顯示了header list。
public void invalidateHeaders()刷新已經(jīng)顯示的header list,會(huì)重新回調(diào)onBuildHeaders()。
public boolean isMultiPane()是否同時(shí)顯示headers和fragment。
public void loadHeadersFromResource(int resid, List target)解析一個(gè)headers的xml然后添加到target列表里。
public void onBuildHeaders(List target)一般需要重寫,注意!這個(gè)函數(shù)可能不是總會(huì)被調(diào)用,例如,如果該Activity已被要求顯示一個(gè)特定的Fragment而不需要頭文件,就不需要構(gòu)建Headers,所以不調(diào)運(yùn)。
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args, int titleRes, int shortTitleRes)構(gòu)造一個(gè)顯示Fragment的Intent對(duì)象。
public void onContentChanged()當(dāng)界面發(fā)生變化時(shí)回調(diào)。
public void onHeaderClick(PreferenceActivity.Header header, int position)當(dāng)選擇Headers列表項(xiàng)時(shí)調(diào)用,默認(rèn)實(shí)現(xiàn)調(diào)用startwithfragment或switchtoheader。
public boolean onIsMultiPane()大屏下默認(rèn)實(shí)現(xiàn)是true。
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref)當(dāng)單擊某個(gè)具有與它相關(guān)聯(lián)的gragment類名稱時(shí)調(diào)用。
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)@deprecated,當(dāng)Preference控件被點(diǎn)擊時(shí),觸發(fā)該方法。參數(shù)preference為點(diǎn)擊的對(duì)象,返回值true代表點(diǎn)擊事件已成功捕捉,無(wú)須執(zhí)行默認(rèn)動(dòng)作或者返回上層調(diào)用,例如,不跳轉(zhuǎn)至默認(rèn)Intent。
public void setListFooter(View view)給Headers list設(shè)置foot view。
public void startPreferenceFragment(Fragment fragment, boolean push)起一個(gè)fragment,push決定是否入棧。
public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes, CharSequence titleText, Fragment resultTo, int resultRequestCode)依據(jù)是否multi-pane模式啟動(dòng)一個(gè)preference的fragment(如果是小屏?xí)貑⒁粋€(gè)activity顯示)。
public void startWithFragment(……)啟動(dòng)一個(gè)新的fragment。
public void switchToHeader(……)在大屏multi-pane模式下切換到fragment顯示給定參數(shù)的fragment。
2-4-2 PreferenceFragment相關(guān)屬性方法使用基礎(chǔ)
翻墻點(diǎn)我查看。PreferenceFragment繼承自Fragment,這個(gè)類是3.0以后推薦使用的,用來(lái)處理碎片化問(wèn)題。
該類的常用方法和上面PreferenceActivity的介紹差不多,這里不再詳細(xì)說(shuō)明,只是PreferenceActivity的@deprecated方法在PreferenceFragment中不是@deprecated的而已。
2-4-3 PreferenceManager相關(guān)方法使用基礎(chǔ)
翻墻點(diǎn)我查看。PreferenceManager繼承自O(shè)bject,這個(gè)類其實(shí)我們前一篇《Android應(yīng)用Preference相關(guān)及源碼淺析(SharePreferences篇)》獲取Preference實(shí)例就該說(shuō)明的,這里才說(shuō)而已。
Android中得到SharedPreference的方式有四種:
ContextWrapper.getSharedPreferences(String name, int mode) 可以自己設(shè)置SharedPreference的名字與模式。
Activity.getPreferences(int mode) name是Activity名字,不能設(shè)置。
PreferenceManager.getSharedPreferences() 通過(guò)PreferenceManager維護(hù)一個(gè)SharedPreference,我們可以調(diào)用PreferenceManager的API來(lái)設(shè)置name和mode,并且最終也是調(diào)用到ContextWrapper的getSharedPreferences。
PreferenceManager.getDefaultSharedPreferences(Context context) 得到的SharedPreference是某個(gè)包名下共享私有的,不能讓其他的包訪問(wèn),而且name和mode不能設(shè)置,最終也會(huì)調(diào)用到ContextWrapper的getSharedPreferences。
接下來(lái)簡(jiǎn)單看下PreferenceManager相關(guān)方法,如下:
methoddescription
PreferenceManager.OnActivityDestroyListener當(dāng)所依賴的activity銷毀時(shí)回調(diào)接口。
PreferenceManager.OnActivityResultListener當(dāng)所依賴的activity得到返回result時(shí)回調(diào)接口。
PreferenceManager.OnActivityStopListener當(dāng)所依賴的activity停止時(shí)回調(diào)接口。
public Preference findPreference(CharSequence key)通過(guò)key找到Preference。
public static SharedPreferences getDefaultSharedPreferences(Context context)每個(gè)應(yīng)用有一個(gè)默認(rèn)的preferences文件,通過(guò)該方法獲取。
public SharedPreferences getSharedPreferences()通過(guò)PreferenceManager維護(hù)一個(gè)SharedPreference,可以調(diào)用PreferenceManager的API來(lái)設(shè)置name和mode。
public int getSharedPreferencesMode()獲取當(dāng)前的mode。
public String getSharedPreferencesName()獲取當(dāng)前的name。
public static void setDefaultValues(Context context, String sharedPreferencesName, int sharedPreferencesMode, int resId, boolean readAgain)更加靈活的設(shè)置默認(rèn)值,注意readAgain參數(shù)。
public static void setDefaultValues(Context context, int resId, boolean readAgain)設(shè)置默認(rèn)值,注意readAgain參數(shù)。
public void setSharedPreferencesMode(int sharedPreferencesMode)設(shè)置當(dāng)前的mode。
public void setSharedPreferencesName(String sharedPreferencesName)設(shè)置當(dāng)前的name。
可以看見(jiàn),這個(gè)類其實(shí)也沒(méi)啥介紹的,重點(diǎn)關(guān)注下setDefaultValues的幾個(gè)核心參數(shù)就行。如果我們的設(shè)置項(xiàng)很多,而且每項(xiàng)在代碼中都需要設(shè)置默認(rèn)缺省值,那就推薦使用setDefaultValues方法。在應(yīng)用第一次運(yùn)行時(shí),從preference的xml中獲取缺省值,并生成文件保存(如果已經(jīng)有一個(gè)SharedPrefferences對(duì)象,也會(huì)進(jìn)行更新,就像下面代碼中三四行對(duì)調(diào));不是第一運(yùn)行就不會(huì)改現(xiàn)有保存值。
protected void onCreate(Bundle savedInstanceState) { ...... PreferenceManager.setDefaultValues(this, R.xml.default_value, false); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); String option = prefs.getString("key", null); }12345
好了,控件使用就到這里了。
2-5 Preference控件家族實(shí)例
關(guān)于Preference控件家族的使用比較簡(jiǎn)單,自定義網(wǎng)上也一大把,所以不再給出例子。如果你想看例子可以參考如下:
官方Settings設(shè)計(jì)原理。
Settings源碼。
其他的相關(guān)用法參考API及網(wǎng)絡(luò)例子。
【工匠若水 http://blog.csdn.net/yanbober 轉(zhuǎn)載請(qǐng)注明出處。點(diǎn)我開始Android技術(shù)交流】
3 Preference組件源碼設(shè)計(jì)簡(jiǎn)單分析
扯蛋了這么多,唉,嘆個(gè)氣繼續(xù)吧,接下來(lái)就到了有意思的環(huán)節(jié),源碼結(jié)構(gòu)簡(jiǎn)介。這里只是針對(duì)Preference控件特性介紹分析,不會(huì)過(guò)多追究View及Activity和Fragment細(xì)節(jié),具體View及Activity和Fragment細(xì)節(jié)后面會(huì)寫文章分析的。
3-1 PreferenceFragment源碼淺析
首先還記得上面基礎(chǔ)說(shuō)了,PreferenceFragment使用第一步就是使用其內(nèi)部方法addPreferencesFromResource或者addPreferencesFromIntent設(shè)置源。所以這里我們以addPreferencesFromResource為例來(lái)說(shuō)明,如下源碼:
//PreferenceFragment的方法public void addPreferencesFromResource(int preferencesResId) { //判斷異常說(shuō)明了該方法至少得在super.onCreate方法之后調(diào)運(yùn),以便初始化PreferenceManager requirePreferenceManager(); //這個(gè)前面也介紹過(guò)的,設(shè)置根布局PreferenceScreen setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(), preferencesResId, getPreferenceScreen()));}1234567
接著我們看下setPreferenceScreen方法源碼,如下:
public void setPreferenceScreen(PreferenceScreen preferenceScreen) { //設(shè)置根布局到PreferenceManager里 if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) { //空方法 onUnbindPreferences(); //設(shè)置標(biāo)記,在onActivityCreated方法中有用 mHavePrefs = true; //決定是否重設(shè)bind布局,核心都是為了執(zhí)行bindPreferences方法 if (mInitDone) { postBindPreferences(); } }}123456789
到此接下來(lái)就是bind了,至于在這里通過(guò)Handler發(fā)消息bindPreferences還是在onActivityCreated自動(dòng)調(diào)bindPreferences方法取決于你把a(bǔ)ddPreferencesFromResource方法寫在那個(gè)生命周期方法里。如下我們直接來(lái)看bindPreferences方法,如下源碼:
//這個(gè)方法是搭建顯示的核心方法!!!!!!!!!private void bindPreferences() { //拿到PreferenceManager中存的根視圖PreferenceScreen final PreferenceScreen preferenceScreen = getPreferenceScreen(); if (preferenceScreen != null) { //傳遞當(dāng)前ListView到preferenceScreen的bind方法 preferenceScreen.bind(getListView()); } //PreferenceFragment的空方法 onBindPreferences();}12345
到此可以看見(jiàn)PreferenceFragment里bind最終是交給了PreferenceScreen的bind來(lái)關(guān)聯(lián)PreferenceFragment的ListView與PreferenceScreen的ListAdapter。我們現(xiàn)在就來(lái)看下PreferenceScreen的bind源碼,如下:
//PreferenceScreen類的方法public void bind(ListView listView) { //設(shè)置listview的item監(jiān)聽 listView.setOnItemClickListener(this); //PreferenceScreen中bind的重點(diǎn)核心!!!!!!!!!!!!!給listview設(shè)置adapter listView.setAdapter(getRootAdapter()); //一些register操作,忽略 onAttachedToActivity();}123456
好了,我們還是來(lái)關(guān)注這個(gè)adapter咋來(lái)的吧,如下就是getRootAdapter方法源碼:
public ListAdapter getRootAdapter() { if (mRootAdapter == null) { mRootAdapter = onCreateRootAdapter(); } return mRootAdapter;}protected ListAdapter onCreateRootAdapter() { return new PreferenceGroupAdapter(this);}1234567891011
終于真相快要大白了,PreferenceFragment的listview設(shè)置的adapter原來(lái)是PreferenceGroupAdapter。哈哈,我們繼續(xù)來(lái)看看這個(gè)類,如下:
//hide類,專門用來(lái)Preference的list顯示的adapterpublic class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeInternalListener {//省略相關(guān)屬性定義 ...... //構(gòu)造方法,傳入的是PreferenceScreen根布局 public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) { ...... //sync設(shè)置相關(guān)list列表數(shù)據(jù)后通知listview刷新 syncMyPreferences(); } private void syncMyPreferences() { ...... //通知listview刷新當(dāng)前準(zhǔn)備的Preference列表 notifyDataSetChanged(); ...... } //省略一堆方法 ...... //notifyDataSetChanged后和普通adapter一樣item繪制會(huì)回調(diào)getView方法 public View getView(int position, View convertView, ViewGroup parent) { //拿到當(dāng)前item的Preference組件 final Preference preference = this.getItem(position); ...... //調(diào)運(yùn)Preference的getView方法得到當(dāng)前item真正的view顯示,這是核心!!!!!!!!!!!! //關(guān)于Preference的getView方法下面分析Preference源碼會(huì)說(shuō)到的,或者你可以直接跳到Preference源碼分析部分查看。 View result = preference.getView(convertView, parent); ...... return result; } ......}1234567891011121314151617181920212223242526272829303132
到此你會(huì)發(fā)現(xiàn),其實(shí)無(wú)非就是ListView和Adapter的關(guān)系,而Adapter的getView所得到的View由Preference提供而已,而Adapter由PreferenceScreen管理而已。
3-2 PreferenceActivity源碼淺析
說(shuō)到PreferenceActivity現(xiàn)在不推薦的addPreferencesFromResource方法時(shí)其實(shí)是沒(méi)啥解釋的,這種模式現(xiàn)在被官方推薦通過(guò)PreferenceFragment的addPreferencesFromResource來(lái)實(shí)現(xiàn),所以也就是說(shuō)關(guān)于PreferenceActivity的addPreferencesFromResource方法(也就是在PreferenceActivity中直接添加Preference組件)其顯示原理和上面分析的PreferenceFragment是一樣的,所以這里就不再過(guò)多解釋了。
我們把重點(diǎn)放在loadHeadersFromResource方法上,也就是現(xiàn)在推薦的PreferenceActivity放置Headers模式。接下來(lái)就來(lái)分析分析吧。
public abstract class PreferenceActivity extends ListActivity implements PreferenceManager.OnPreferenceTreeClickListener, PreferenceFragment.OnPreferenceStartFragmentCallback {...... //省略一堆方法 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //設(shè)置基礎(chǔ)布局 setContentView(com.android.internal.R.layout.preference_list_content); //獲取一些ContentView里的控件實(shí)例 ...... //判斷是啥模式,左右展示還是單頁(yè) boolean hidingHeaders = onIsHidingHeaders(); mSinglePane = hidingHeaders || !onIsMultiPane(); //獲取fragment參數(shù)(其實(shí)是PreferenceActivity中點(diǎn)擊Header item重啟PreferenceActivity時(shí)傳遞的) String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS); int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0); if (savedInstanceState != null) { ...... //忽略,非重點(diǎn)主線 } else { if (initialFragment != null && mSinglePane) { //SinglePane時(shí)有參數(shù)則替換顯示Fragment switchToHeader(initialFragment, initialArguments); ...... } else { //核心方法之一!!!!!!!!!!!! //記得上面基礎(chǔ)使用介紹過(guò)嗎?新的實(shí)現(xiàn)重寫onBuildHeaders空方法,在其中 //調(diào)運(yùn)loadHeadersFromResource方法加載header list xml文件 onBuildHeaders(mHeaders); //如果存在header list則走這里(上面onBuildHeaders里會(huì)組織生成mHeaders的list結(jié)構(gòu)) if (mHeaders.size() > 0) { //header-fragment左右各半屏模式 if (!mSinglePane) { if (initialFragment == null) { //設(shè)置顯示header Header h = onGetInitialHeader(); switchToHeader(h); } else { //設(shè)置顯示header及fragment switchToHeader(initialFragment, initialArguments); } } } } } if (initialFragment != null && mSinglePane) { //當(dāng)SinglePane加載的是Fragment時(shí)隱藏header,顯示fragment findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE); mPrefsContainer.setVisibility(View.VISIBLE); ...... } else if (mHeaders.size() > 0) { //重點(diǎn)!!!!!!!!!!!!!!!!!這就是要分析的header的listview的adapter放置地 setListAdapter(new HeaderAdapter(this, mHeaders)); ...... } else { //這就是最原始的供已經(jīng)不推薦的addPreferencesFromResource方式加載Preference組件了 //具體原理同上PreferenceFragment的加載顯示原理了,不再分析 setContentView(com.android.internal.R.layout.preference_list_content_single); ...... } //其他初始設(shè)置 ...... }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
通過(guò)上面的分析可以看見(jiàn)其實(shí)對(duì)于Header的adapter核心就是setListAdapter(new HeaderAdapter(this, mHeaders));這句代碼。那我們就來(lái)看看這個(gè)內(nèi)部類HeaderAdapter,源碼如下:
//可以發(fā)現(xiàn)PreferenceActivity的內(nèi)部類HeaderAdapter是繼承自ArrayAdapter的,//這個(gè)Adapter就是用來(lái)給推薦的Header list的listview提供數(shù)據(jù)的。private static class HeaderAdapter extends ArrayAdapter {//Holder里只有最典型經(jīng)典的三個(gè)組件 private static class HeaderViewHolder {ImageView icon; TextView title; TextView summary; } private LayoutInflater mInflater; //構(gòu)造方法,不解釋 public HeaderAdapter(Context context, List objects) { super(context, 0, objects); mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } //最最核心方法!!!!!!Header list被顯示到PreferenceActivity的listview關(guān)鍵點(diǎn) @Override public View getView(int position, View convertView, ViewGroup parent) { HeaderViewHolder holder; View view; //再常見(jiàn)不過(guò)的Adapter數(shù)據(jù)加載ViewHolder寫法了 if (convertView == null) { //加載header的item布局,都是用的preference_header_item文件,如下會(huì)介紹 view = mInflater.inflate(com.android.internal.R.layout.preference_header_item, parent, false); holder = new HeaderViewHolder(); holder.icon = (ImageView) view.findViewById(com.android.internal.R.id.icon); holder.title = (TextView) view.findViewById(com.android.internal.R.id.title); holder.summary = (TextView) view.findViewById(com.android.internal.R.id.summary); view.setTag(holder); } else { view = convertView; holder = (HeaderViewHolder) view.getTag(); } //一堆顯示,通過(guò)getItem(position)拿到構(gòu)造里傳入的List類型objects的item // All view fields must be updated every time, because the view may be recycled Header header = getItem(position); holder.icon.setImageResource(header.iconRes); holder.title.setText(header.getTitle(getContext().getResources())); CharSequence summary = header.getSummary(getContext().getResources()); if (!TextUtils.isEmpty(summary)) { holder.summary.setVisibility(View.VISIBLE); holder.summary.setText(summary); } else { holder.summary.setVisibility(View.GONE); } return view; }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
可以看見(jiàn)這個(gè)adapter的getView中的item核心是加載了一個(gè)preference_header_item的xml文件,然后設(shè)置作為item的header。這個(gè)xml源碼如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
哈哈,到此就不在解釋啥了,很直觀了,就是這么任性,就是這么簡(jiǎn)單的實(shí)現(xiàn)了Header List的顯示。
3-3 Preference源碼淺析
說(shuō)這個(gè)的原因是上面PreferenceFragemnt分析加載設(shè)置adapter的getView方法時(shí)留下的歷史問(wèn)題。我們先來(lái)看看這個(gè)文件的核心代碼,后面總結(jié)串起來(lái)你就明白了,如下源碼:
//可以看見(jiàn),他不是一個(gè)View,但是組合管理了一個(gè)View和PreferenceManagerpublic class Preference implements Comparable{...... //各種屬性 ...... private PreferenceManager mPreferenceManager; //重點(diǎn)關(guān)注,和自定義及Preference顯示原理息息相關(guān),preference就是下面列出的xml資源 private int mLayoutResId = com.android.internal.R.layout.preference; private int mWidgetLayoutResId; ...... //各種getXXX及setXXX方法 ...... /** * Gets the View that will be shown in the {@link PreferenceActivity}. * 獲取Preference的item顯示view */ public View getView(View convertView, ViewGroup parent) { if (convertView == null) { convertView = onCreateView(parent); } onBindView(convertView); return convertView; } protected View onCreateView(ViewGroup parent) { final LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View layout = layoutInflater.inflate(mLayoutResId, parent, false); final ViewGroup widgetFrame = (ViewGroup) layout.findViewById(com.android.internal.R.id.widget_frame); if (widgetFrame != null) { //mWidgetLayoutResId有專門的set方法可以設(shè)置或者重寫 if (mWidgetLayoutResId != 0) { //android:id/widget_frame為mWidgetLayoutResId所對(duì)應(yīng)的布局預(yù)留空間插入 layoutInflater.inflate(mWidgetLayoutResId, widgetFrame); } else { //默認(rèn)實(shí)現(xiàn)是null的 widgetFrame.setVisibility(View.GONE); } } return layout; } /** * Binds the created View to the data for this Preference. ** This is a good place to grab references to custom Views in the layout and * set properties on them. * */ protected void onBindView(View view) { //設(shè)置子View相關(guān)屬性 final TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title); if (titleView != null) { final CharSequence title = getTitle(); if (!TextUtils.isEmpty(title)) { titleView.setText(title); titleView.setVisibility(View.VISIBLE); } else { titleView.setVisibility(View.GONE); } } ...... //類似的各種子View設(shè)置操作,不再列出 } ......}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596
可以看見(jiàn),這個(gè)getView其實(shí)就是上面PreferenceFragment分析中Adapter中g(shù)etView調(diào)運(yùn)的Preference的getView。怎么樣,串起來(lái)吧。也就是說(shuō)Preference不是View,但是他提供View給ListView的每一個(gè)Item顯示,其提供的View的基類布局(上面Preference類中mLayoutResId屬性的值)如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
哈哈,不用解釋了吧,這下相信你可以將前面基礎(chǔ)使用和源碼分析幾部分完全串起來(lái)理解了吧。
3-4 Preference組件家族源碼分析總結(jié)
通過(guò)上面分析可以知道Preference其實(shí)不是View,但是其內(nèi)部創(chuàng)建管理了一個(gè)View(ListView的item,被Adapter的getView通過(guò)Preference.getView方法獲得顯示)。
可以看出來(lái),上面我們分析Preference的onCreateView、getView、onBindView這幾個(gè)方法其實(shí)是整個(gè)Preference組件顯示等的核心方法,所以正如系統(tǒng)提供的Preference的各種實(shí)用子類一樣,當(dāng)我們想自定義Preference的時(shí)候完全可以重寫這些方法來(lái)得到自己的各種自定義View,這樣就完美的解決了代碼的擴(kuò)展性,我們不用去修改ListAdapter的實(shí)現(xiàn)就能實(shí)現(xiàn)自定義的Preference,所以說(shuō)可見(jiàn)Google的工程師在設(shè)計(jì)Preference結(jié)構(gòu)時(shí)是多么的牛叉,不得不膜拜。
【工匠若水 http://blog.csdn.net/yanbober 轉(zhuǎn)載請(qǐng)注明出處。點(diǎn)我開始Android技術(shù)交流】
4 Preference組件家族總結(jié)
題外話:其實(shí)這篇文章是受我一個(gè)朋友邀請(qǐng)幫忙寫的。還記得去年年初我在上家公司(做Android盒子)負(fù)責(zé)修改一個(gè)項(xiàng)目的Settings源碼,添加一個(gè)屏幕縮放功能在Settings里面。后來(lái)做好以后維護(hù)轉(zhuǎn)手給了別人,當(dāng)時(shí)別人是個(gè)新手,各種問(wèn)。所以落下后遺癥,于是乎就在邀請(qǐng)之下打算寫了這一系列兩篇文章,以幫助快速上手原生Settings的修改。
其實(shí)沒(méi)啥總結(jié)的,還記得前段時(shí)間在網(wǎng)上看見(jiàn)有人吐槽Preference是google設(shè)計(jì)的一個(gè)失敗品,一點(diǎn)也不好用啥的。其實(shí)我想說(shuō)Preference的設(shè)計(jì)還是不錯(cuò)的,是值得借鑒的,隨便舉個(gè)例子如下:
在布局設(shè)計(jì)上可以保持統(tǒng)一預(yù)留差異區(qū)域供自定義動(dòng)態(tài)插入,達(dá)到復(fù)用的目的。
在實(shí)現(xiàn)listView各個(gè)item不同的Adapter的getView方法時(shí)不用像傳統(tǒng)那樣if-else或者switch操作,而是預(yù)留一個(gè)基類用于實(shí)現(xiàn)回調(diào),這樣更加靈活。
其他的慢慢體會(huì)就行了。
標(biāo)簽:
相關(guān)推薦:
精彩放送:
- []克羅地亞終獲世界杯季軍,海信電視為每個(gè)強(qiáng)者喝彩
- []棕櫚股份景觀設(shè)計(jì)展現(xiàn)現(xiàn)代與自然的和諧之美
- []世界杯消費(fèi)趨勢(shì)洞察:大屏電視翻倍增長(zhǎng),ULED電視奪冠
- []世界杯觀賽調(diào)研公布: Z世代消費(fèi)者首選海信電視
- []【東海期貨12月20日產(chǎn)業(yè)鏈日?qǐng)?bào)】能化篇:中國(guó)需求預(yù)期提振,油價(jià)小漲
- []環(huán)球即時(shí)看!三立期貨12月20日早間內(nèi)參——宏觀
- []十八數(shù)藏創(chuàng)始人柏松受邀出席“西部國(guó)家版權(quán)鏈”發(fā)布會(huì)并作主題發(fā)言
- []廣西文旅產(chǎn)業(yè)簽約6個(gè)重大項(xiàng)目 計(jì)劃總投資額達(dá)113.6億元
- []今日看點(diǎn):五礦地產(chǎn)獲授7.8億港元循環(huán)貸款額度
- []千紅制藥:公司臨床階段新藥各項(xiàng)工作均在正常推進(jìn)中,請(qǐng)關(guān)注公司定期報(bào)告與臨時(shí)公告
- []世界信息:三湘印象擬非公開發(fā)行股票,募集資金總額不超16億元
- []天天速遞!12月LPR連續(xù)4個(gè)月維持不變:1年期3.65%、5年期4.30%
- []利民股份:公司子公司江蘇卓邦新能源科技有限公司擬投資建設(shè)新能源電池用電解質(zhì)鹽、功能添加劑及電解液項(xiàng)目
- []每日視點(diǎn)!華夏幸福:相關(guān)債務(wù)置換議案獲董事會(huì)通過(guò)
- []當(dāng)前看點(diǎn)!三木集團(tuán):公司的經(jīng)營(yíng)一切正常
- []旅游年票發(fā)行大勢(shì)所趨,專家:要體現(xiàn)出誠(chéng)意
- []【新要聞】重慶九龍坡區(qū)落戶13個(gè)重點(diǎn)項(xiàng)目 總投資139.23億元
- []環(huán)球聚焦:住建部:1-10月老舊小區(qū)改造開工率已達(dá)101.7%
- []旭輝將配售8.4億股現(xiàn)有股份 所得款凈額約9.46億港元
- []大消息!500強(qiáng)金融巨頭罕見(jiàn)出手,50億拿下上海外灘核心地塊
- []全球熱點(diǎn)評(píng)!廣東肇慶1宗商住地將于2023年1月5日出讓 起價(jià)1.2億元
- []世界百事通!深圳機(jī)場(chǎng)啟動(dòng)物流設(shè)施建設(shè)項(xiàng)目 總投資超50億元
- []天天訊息:新致軟件:本次可轉(zhuǎn)債的募投項(xiàng)目正在按既定計(jì)劃推進(jìn),具體進(jìn)度請(qǐng)關(guān)注公司相關(guān)公告
- []天天速讀:首都機(jī)場(chǎng):尤為艱難
- []公攤面積內(nèi)衛(wèi)生間“消失”,業(yè)主起訴房地產(chǎn)公司獲賠償
- []房產(chǎn)中介推銷“添油加醋” 購(gòu)房者需提高警惕
- []焦點(diǎn)短訊!塔里木油田向新疆南部累計(jì)供氣500億立方米
- []今日熱聞!道通科技數(shù)字能源中國(guó)區(qū)產(chǎn)品發(fā)布會(huì)擬于12月22日舉行
- []動(dòng)態(tài):新疆為何能成為中國(guó)電力新高地?
- []環(huán)球信息:上海實(shí)業(yè)控股46.08億出售上海實(shí)森90%股權(quán)及相關(guān)債權(quán)予友邦人壽
- []全球快播:車損包括哪些險(xiǎn)種
- []不買交強(qiáng)險(xiǎn)上路會(huì)怎樣 上路車輛不買交強(qiáng)險(xiǎn)會(huì)怎樣
- []賦能電力數(shù)字化多樣場(chǎng)景 ——深信服云邊安一體化建設(shè)方案助力發(fā)電行業(yè)數(shù)字化轉(zhuǎn)型
- []要聞:網(wǎng)上交車保險(xiǎn)怎么辦理 如何在網(wǎng)上交車險(xiǎn)
- []儲(chǔ)能電池主要應(yīng)用在哪些地方?
- []世界快消息!棗莊99元的惠民保險(xiǎn)在哪里買 在哪里買棗莊99元的惠民保險(xiǎn)
- []實(shí)時(shí):怎么查詢自己車輛保險(xiǎn)是哪個(gè)公司 自己車輛保險(xiǎn)是哪個(gè)公司怎么查詢
- []滾動(dòng):因現(xiàn)行市況 達(dá)美樂(lè)中國(guó)特許經(jīng)營(yíng)商達(dá)勢(shì)股份延遲全球發(fā)售
- []華發(fā)股份選舉李偉杰為第十屆監(jiān)事會(huì)監(jiān)事長(zhǎng)?
- []今頭條!美股盤前:特斯拉升逾3% 中概股輕微上升 阿里升逾3%
- []拓新藥業(yè):12月16日公司高管蔡玉瑛、渠桂榮、董春紅減持公司股份合計(jì)11.14萬(wàn)股
- []今日聚焦!土地周報(bào) | 重點(diǎn)城市土地供應(yīng)“斷檔”,市場(chǎng)熱度繼續(xù)下行(12.12-12.18)
- []快報(bào):遠(yuǎn)洋集團(tuán)與郵儲(chǔ)銀行簽署全面戰(zhàn)略合作協(xié)議 獲180億元授信額度
- []全球觀焦點(diǎn):房地產(chǎn)逆周期之下,貝殼如何詮釋“堅(jiān)持難而正確的事”?
- []環(huán)球快報(bào):道道全:12月16日公司高管張軍減持公司股份合計(jì)6.5萬(wàn)股
- []九典制藥:12月16日公司高管段立新減持公司股份合計(jì)15.51萬(wàn)股
- []中國(guó)建筑1-11月地產(chǎn)業(yè)務(wù)合約銷售額3484億元
- []全球今熱點(diǎn):三湘印象擬非公開發(fā)行股票 募集資金總額不超過(guò)16億
- []全球最資訊丨璞泰來(lái):12月16日至12月19日公司高管陳衛(wèi)增持公司股份合計(jì)3.25萬(wàn)股
- []全球微動(dòng)態(tài)丨廣東東莞4宗地塊56億成交,華潤(rùn)聯(lián)合體29億斬獲交椅灣地塊
- []當(dāng)前消息!萬(wàn)科董事會(huì)審議通過(guò)發(fā)行境外上市外資股(H股)方案
- []【全球報(bào)資訊】統(tǒng)聯(lián)精密:12月16日公司高管楊虎增持公司股份合計(jì)5000股
- []龍軟科技:12月15日公司高管任永智減持公司股份合計(jì)1.24萬(wàn)股
- []中交地產(chǎn):3個(gè)交易日收盤價(jià)漲幅累計(jì)20%,無(wú)應(yīng)披未披重大事項(xiàng)
- []焦點(diǎn)關(guān)注:天津第四批供地收官:24宗地收金99.8億元,僅2宗溢價(jià)成交
- []直播預(yù)告|一起來(lái)看旅游業(yè)“神仙打架”名場(chǎng)面!
- []今日?qǐng)?bào)丨南都電源:公司股東人數(shù)請(qǐng)參見(jiàn)公司定期報(bào)告
- []當(dāng)前快訊:快訊丨華發(fā)股份:選舉李偉杰任監(jiān)事長(zhǎng)
- []前11個(gè)月上海商品房銷售面積約1526萬(wàn)平方米
- []世界今頭條!家居丨奧普家居:回購(gòu)注銷限制性股票合計(jì)279.8萬(wàn)股
- []財(cái)面兒丨大悅城完成發(fā)行15億元公司債券 票面利率為4.27%
- []【世界新要聞】昊華能源虛假陳述案開庭 投資者索賠金額已超億元
- []名臣健康:12月16日公司高管彭小青減持公司股份合計(jì)27.9萬(wàn)股
- []簡(jiǎn)訊:招商局蛇口36.4億元公司債將上市 利率分別為2.40%、2.80%
- []世界觀點(diǎn):首開股份:完成發(fā)行10億元中期票據(jù) 票面利率5%
- []全球報(bào)道:金逸影視: 公司暫未涉及上述業(yè)務(wù)。 祝您生活愉快,投資順利!
- []天天視訊!新希望地產(chǎn)累計(jì)獲綜合授信超480億元
- []實(shí)時(shí):北上廣深等13市共同發(fā)布《城市治理現(xiàn)代化北京宣言》
- []當(dāng)前簡(jiǎn)訊:洲明科技:公司具體產(chǎn)量、銷量及投產(chǎn)情況詳見(jiàn)公司于巨潮資訊網(wǎng)披露的定期報(bào)告及相關(guān)公告
- []當(dāng)前視訊!金科股份:截至 2022年11月末,公司已到期未支付的債務(wù)本金合計(jì)金額90.91億元
- []徽商期貨榮獲和訊第20屆中國(guó)財(cái)經(jīng)風(fēng)云榜“2022年度品牌影響力期貨公司”
- []2元20片退燒藥沖上熱搜第一 股價(jià)一字漲停!東北制藥的背后是...?
- []嶺南控股:截至目前,公司的控股子公司廣州廣之旅國(guó)際旅行社股份有限公司的出入境旅游組團(tuán)業(yè)務(wù)尚未恢復(fù)
- []每日觀點(diǎn):金融街威斯汀酒店30.01億元資產(chǎn)支持ABS已獲受理
- []每日視訊:中鐵建設(shè)創(chuàng)業(yè)大廈6.7億元資產(chǎn)支持ABS(類REITs)已獲受理
- []深圳南山將再發(fā)2億元消費(fèi)券,推出近百場(chǎng)線上線下促消費(fèi)活動(dòng)
- []通訊!中海企業(yè)發(fā)展30億元公司債券票面利率為2.7%
- []全球熱頭條丨襄陽(yáng)住房投資10億元公司債券已獲受理
- []【環(huán)球播資訊】【券商聚焦】中信證券指地產(chǎn)市場(chǎng)拐點(diǎn)有望顯現(xiàn) 推薦萬(wàn)科企業(yè)(02202)等優(yōu)秀開發(fā)企業(yè)
- []ST三圣:百康藥業(yè)暫無(wú)擴(kuò)產(chǎn)計(jì)劃,將全力保障生產(chǎn)經(jīng)營(yíng),滿足目前市場(chǎng)需求
- []至純科技:公司8寸涂膠顯影設(shè)備正在驗(yàn)證中
- []世界簡(jiǎn)訊:天津四批次集中供地收官,全年總成交額315億元
- []迪馬股份:陳涵辭任公司副總裁職務(wù)
- []環(huán)球觀點(diǎn):上周樓市整體環(huán)比略有上漲,同比持續(xù)下降,土地供求環(huán)比走高,宅地成交量增近三成
- []得利斯:今年以來(lái),預(yù)制菜產(chǎn)品銷量較去年同期有較大幅度增長(zhǎng)
- []每日熱文:夢(mèng)潔股份:公司實(shí)施高端品牌戰(zhàn)略,為顧客提供高品質(zhì)的家居生活方式,傳導(dǎo)充滿愛(ài)的家居生活態(tài)度
- []全球熱推薦:通行寶:公司近日暫無(wú)資產(chǎn)出售和收購(gòu)重組等的計(jì)劃,后續(xù)信息請(qǐng)以公司公告為準(zhǔn)
- []達(dá)安基因:公司全資子公司中山生物工程有限公司已進(jìn)入24小時(shí)持續(xù)生產(chǎn)狀態(tài)中,已經(jīng)面向國(guó)內(nèi)市場(chǎng)銷售
- []【天天快播報(bào)】市場(chǎng)看漲情緒高漲,2022年黃金有望強(qiáng)勁收官!
- []環(huán)球即時(shí):美原油交易策略:下行趨勢(shì)線壓制明顯,提防進(jìn)一步下探風(fēng)險(xiǎn)
- []當(dāng)前時(shí)訊:12月19日匯市觀潮:歐元、英鎊和日元技術(shù)分析
- []環(huán)球熱點(diǎn)!蜂巢能源第三屆電池日發(fā)布超300Ah大容量?jī)?chǔ)能電池引領(lǐng)新風(fēng)向
- []熱點(diǎn)評(píng)!現(xiàn)貨黃金交易策略:美聯(lián)儲(chǔ)進(jìn)一步加息前景抵消美元走軟影響,金價(jià)仍有見(jiàn)頂風(fēng)險(xiǎn)
- []【華安期貨】貴金屬12月18日周報(bào):12月加息落地,金價(jià)延續(xù)偏強(qiáng)態(tài)勢(shì)
- []每日播報(bào)!國(guó)產(chǎn)客機(jī)再入印尼,能否雪恥撲朔迷離
- []信息:北京大部分酒店已恢復(fù)承辦婚宴、公司年會(huì),接受年夜飯預(yù)訂
- []當(dāng)前通訊!長(zhǎng)三角鐵路多地客流增幅明顯,加開多個(gè)方向旅客列車保障出行
- []天天速看:民航:明年1月初先恢復(fù)到疫情前七成航班量
- []當(dāng)前熱文:上千條魚涌入柏林市中心,麗笙酒店內(nèi)世界最大圓柱水族箱炸裂
- []全球頭條:12月19日海源復(fù)材漲停分析:蔚來(lái)汽車概念股,寧德時(shí)代概念股,碳纖維概念熱股
- Makefile宏控是什么?宏控與systemProperty取名對(duì)應(yīng)
- 全球熱點(diǎn)!QGIS|構(gòu)建選址模型 模型需求分析
- 世界速訊:視頻在html不能播放器怎么辦?網(wǎng)頁(yè)播放器打不開的解決方法
- 看熱訊:QT部署YOLOV5 pyqt5搭建YOLOV5的檢測(cè)平臺(tái)
- Android應(yīng)用Preference相關(guān)及源碼淺析 Preference相關(guān)基礎(chǔ)概念
- 世界速看:2021慶陽(yáng)一中高考成績(jī)查詢 2020年慶陽(yáng)市多所中學(xué)高考喜報(bào)
- 一個(gè)沒(méi)有四肢的人 卻給了無(wú)數(shù)人的力量
- 今日觀點(diǎn)!Win7安裝IE10或IE11怎么操作?離線安裝注意問(wèn)題
- 《阿凡達(dá)2》重磅回歸,聯(lián)手海信電視呈現(xiàn)光影之美
- ? 《阿凡達(dá)2》震撼首映,與海信電視攜手上演“美學(xué)巔峰”
- B站注冊(cè)資本增幅400%至5億 目前由陳睿全資持股
- 光源資本出任獨(dú)家財(cái)務(wù)顧問(wèn) 沐曦集成電路10億元A輪融資宣告完成
- 巨輪智能2021年上半年?duì)I收11.24億元 期內(nèi)研發(fā)費(fèi)用投入增長(zhǎng)19.05%
- 紅棗期貨尾盤拉升大漲近6% 目前紅棗市場(chǎng)總庫(kù)存約30萬(wàn)噸
- 嘉銀金科發(fā)布2021年Q2財(cái)報(bào) 期內(nèi)凈利潤(rùn)達(dá)1.27億元同比增長(zhǎng)208%
- 成都銀行2021上半年凈利33.89億元 期內(nèi)實(shí)現(xiàn)營(yíng)收同比增長(zhǎng)17.27億元
- 汽車之家發(fā)布2021年第二季度業(yè)績(jī) 期內(nèi)新能源汽車品牌收入增長(zhǎng)238%
- 中信銀行上半年實(shí)現(xiàn)凈利潤(rùn)290.31億元 期末不良貸款余額706.82億元
- 光伏概念掀起漲停潮交易價(jià)格創(chuàng)新高 全天成交額達(dá)1.29億元
- 上半年生物藥大增45% 關(guān)鍵財(cái)務(wù)指標(biāo)好轉(zhuǎn)營(yíng)收賬款持續(xù)下降
- 全球熱點(diǎn)!12月19日全 聚 德漲停分析:餐飲,預(yù)制菜,休閑食品概念熱股
- 天天速讀:上海松江今年推出1701套公租房
- 博眾精工:牽手蜂巢能源 疊片機(jī)設(shè)備領(lǐng)域?qū)O具競(jìng)爭(zhēng)優(yōu)勢(shì)
- 每日熱門:中交地產(chǎn):10億元公司債券票面利率為5.9%
- 阿根廷斬獲大力神杯 海信電視見(jiàn)證梅西圓夢(mèng)卡塔爾
- 全球速看:浙江義烏3宗地塊40.9億元成交
- 天天快消息!合景泰富擬配售2.35億股 籌資4.67億港元
- 越秀地產(chǎn)上市30年,高質(zhì)量發(fā)展再謀新篇
- 環(huán)球資訊:12月19日悅心健康漲停分析:養(yǎng)老產(chǎn)業(yè),裝修裝飾,口腔概念熱股
- 全球信息:12月19日黑芝麻漲停分析:鋰電池,新能源汽車,休閑食品概念熱股
- 利德治療儀 多年良心價(jià)格回報(bào)客戶
- 梅西加冕!海信電視為潘帕斯雄鷹喝彩
- 觀速訊丨install安裝命令的常見(jiàn)用法 install有哪些優(yōu)點(diǎn)?
- 天天快看點(diǎn)丨vue怎么引入阿里巴巴圖標(biāo)?引入的方法教程
- 世界熱頭條丨英偉達(dá)開發(fā)板中的編譯系統(tǒng) 能否在ZC706的板子上執(zhí)行?
- 全球今亮點(diǎn)!sprintf函數(shù)是什么?sprintf函數(shù)用法的詳解
- 全球快播:什么是黑蘋果系統(tǒng)?黑蘋果Mac系統(tǒng)安裝教程
- 今日精選:Linux命令之restore命令 使用語(yǔ)法及參數(shù)說(shuō)明
- 報(bào)道:ICMP是什么意思?ICMP的詳解
- 世界消息!Steam賬號(hào)怎么注冊(cè)?Steam賬號(hào)注冊(cè)流程
- 【世界快播報(bào)】深入理解BootStrap--面板panel BootStrap的原理分析
- 【環(huán)球熱聞】杳無(wú)音信拼音怎么讀?杳無(wú)音信的含義
- 送嬰兒選什么禮物好?送嬰兒禮物排行榜
- 當(dāng)前報(bào)道:什么是audit? audit可以用來(lái)干什么?
- 當(dāng)前熱議!什么是 “云”?云的最后形成
- group by是什么意思?關(guān)于group by的用法和原理
- 全球消息!好萊塢十大最可愛(ài)的女演員是誰(shuí)?瑪麗昂歌迪亞僅排末尾
- 天天熱議:【音頻】syntax How to Write Custom Syntax
- JAVA的forEach用法是什么?JAVA的forEach的格式
- 【環(huán)球播資訊】大蛇丸的兒子的母親 大蛇丸的老婆是誰(shuí)?
- 環(huán)球滾動(dòng):戰(zhàn)地4配置要求有哪些?推薦幾個(gè)戰(zhàn)地4配置
- 世界球精選!石家莊核酸檢測(cè)20-22號(hào)完成 24號(hào)低風(fēng)險(xiǎn)區(qū)域會(huì)讓出門嗎?
- 天天即時(shí)看!QPS是什么?QPS的計(jì)算方法
- 全球今亮點(diǎn)!box-shadow屬性語(yǔ)法 box-shadow屬性詳解
- 微頭條丨咐組詞和拼音是什么?咐怎么讀?
- linux中常用的sftp命令有哪些?sftp介紹
- 即時(shí)焦點(diǎn):youbastard怎么發(fā)音?youbastard的含義
- 世界速遞!sql中的left join 查詢 left join之后的記錄有幾條?
- 全球觀點(diǎn):瘦金體由誰(shuí)所創(chuàng)?關(guān)于瘦金體由誰(shuí)所創(chuàng)的介紹
- 如何禁用Windows期自動(dòng)更新?禁用方法步驟
- 全球信息:乘風(fēng)破浪的姐姐四公淘汰了誰(shuí)?乘風(fēng)破浪的姐姐復(fù)活名單
- 環(huán)球報(bào)道:泰山門票多少錢一張2022 泰山門票價(jià)格
- 環(huán)球速遞!Windows 10怎么重新安裝微軟商店Microsoft Store?方法步驟
- 天天熱訊:《愛(ài)的厘米》好看嗎?佟麗婭佟大為撒狗糧 郭家銘與男主再續(xù)兄弟情
- 世界熱議:林丹的個(gè)人資料曝光 林丹是誰(shuí)?
- 視焦點(diǎn)訊!索愛(ài)手機(jī)w800c怎么樣?索愛(ài)手機(jī)w800c綜合評(píng)測(cè)與最新報(bào)價(jià)
- 環(huán)球熱資訊!王力宏被娃哈哈解約后 看到他隨身攜帶的水太佩服
- 環(huán)球?qū)崟r(shí):長(zhǎng)絲巾有哪些系法?長(zhǎng)絲巾的系法圖解
- 世界通訊!捷安特770d怎么樣?捷安特770d詳細(xì)評(píng)測(cè)
- 硬盤s.m.a.r.t指標(biāo)數(shù)據(jù)異常修復(fù)工具 硬盤的s m a r t指標(biāo)數(shù)據(jù)異常怎么修復(fù)?
- 311是什么意思?關(guān)于311的詳情介紹
- 世界簡(jiǎn)訊:HTC One X Recovery一鍵刷入步驟介紹 HTC One X Recovery一鍵刷入教程
- 當(dāng)前快報(bào):htc是什么牌子?htc手機(jī)的評(píng)測(cè)
- 環(huán)球熱資訊!臺(tái)式機(jī)硬盤報(bào)價(jià)如何?臺(tái)式機(jī)硬盤尺寸
- 世界報(bào)道:羽毛球奧運(yùn)冠軍都有誰(shuí)?國(guó)羽男子奧運(yùn)冠軍排名
- 全球球精選!諾亞舟np360學(xué)習(xí)機(jī)怎么樣?諾亞舟np360性能介紹
- 定位賽10連勝什么段位?LOL S5定位賽勝率高為什么沒(méi)有上段?
- 即時(shí)焦點(diǎn):三星9050好不好?三星9050如何刷機(jī)?
- 世界時(shí)訊:純甲類功放價(jià)格參考及其介紹 純甲類功放的價(jià)格
- 世界快看點(diǎn)丨聯(lián)想S890支持什么視頻格式?聯(lián)想S890支持RMVB播放嗎?
- 操作系統(tǒng)有哪些類型?操作系統(tǒng)的特點(diǎn)是什么?
- 世界熱文:手機(jī)鋼化膜哪個(gè)品牌質(zhì)量好?手機(jī)鋼化膜的優(yōu)缺點(diǎn)是什么?
- 死或生5最后一戰(zhàn)怎么反擊?死或生5最后一戰(zhàn)反擊技巧攻略
- 環(huán)球視點(diǎn)!諧波減速機(jī)優(yōu)點(diǎn)是什么?齒輪式怎么滾動(dòng)?
- 焦點(diǎn)快報(bào)!計(jì)算機(jī)主板結(jié)構(gòu)你了解多少?計(jì)算機(jī)主板的分類
- 報(bào)道:計(jì)算機(jī)撥號(hào)連接無(wú)法建立連接怎么辦?電信撥號(hào)上網(wǎng)連接不上的解決方法
- 怎么用電腦攝像頭錄像?電腦攝像頭錄像的使用方法
- APP(ios、Android)實(shí)現(xiàn)充值的方案 ios中充值功能的2種方案
- 暴風(fēng)影音如何倍速播放?暴風(fēng)影音倍數(shù)播放的方法
- Cubase延音踏板怎么設(shè)置?Cubase延音踏板設(shè)置延音效果
- 瀏覽器市場(chǎng)占有率排行表 2020年8月國(guó)內(nèi)瀏覽器排行
- 【環(huán)球新要聞】人工智能算法是什么?簡(jiǎn)化圖形文件
- 環(huán)球微動(dòng)態(tài)丨光電耦合器是什么?光電耦合器工作原理詳解
- 焦點(diǎn)簡(jiǎn)訊:百度云盒怎么預(yù)約購(gòu)買?電視應(yīng)用購(gòu)買教程
- 全球微頭條丨vice versa是什么意思?vice versa通常翻譯
- 【環(huán)球報(bào)資訊】咸魚Maya筆記 Maya界面是怎么組成的?
- 520還在畫玫瑰?教你用MATLAB畫個(gè)玫瑰花球
- 賓得鏡頭簡(jiǎn)介 鏡頭術(shù)語(yǔ)都有哪些?
- 世界熱門:百度如何清除搜索框內(nèi)的搜索歷史記錄?清除歷史記錄
- 小米與華為手機(jī)哪個(gè)好些?小米與華為手機(jī)詳細(xì)評(píng)測(cè)
- 華為榮耀4C詳細(xì)評(píng)測(cè) 再次刷新安卓手機(jī)性價(jià)比
- 世界新動(dòng)態(tài):人生中的第一個(gè)Java程序:HelloWorld
- 世界視點(diǎn)!arp防火墻哪個(gè)最好?風(fēng)云arp防火墻的基本介紹
- 聯(lián)想服務(wù)器linux系統(tǒng)raid驅(qū)動(dòng) IntelRAID 6.12版RAID卡驅(qū)動(dòng)官方正式版下載
- 環(huán)球觀速訊丨有哪些好看的電影推薦?吐血推薦250部必看電影
- 微動(dòng)態(tài)丨我們?yōu)槭裁匆蠈W(xué)?奧巴馬開學(xué)演講稿
- 環(huán)球熱點(diǎn)!我的世界android制作教程 我的世界怎么去月球?
- 當(dāng)前滾動(dòng):安卓怎么開啟啟動(dòng)模式?Android四種啟動(dòng)模式
- 當(dāng)前速讀:南陽(yáng)五中2021年高考成績(jī)查詢時(shí)間 南陽(yáng)市五中舉行2021年春期開學(xué)典禮
- 世界訊息:E. Border是什么?拓展歐幾里得+mod分析
- 世界微資訊!電阻式觸摸屏好用嗎?電阻式觸摸屏工作原理
- 實(shí)時(shí):AssemblyInfo.cs文件的作用是什么?AssemblyInfo.cs文件詳情
- 焦點(diǎn)熱訊:小眾國(guó)度酒店,如何異國(guó)生長(zhǎng)?
- 世界時(shí)訊:中國(guó)鐵建轉(zhuǎn)讓蘇州京發(fā)地產(chǎn)30%股權(quán) 廣州新鐵鑫建接盤
- 今日播報(bào)!富臨運(yùn)業(yè):截至2022年12月9日,公司股東人數(shù)為24,367人
- 華盛昌:公司正在積極推進(jìn)呼吸機(jī)產(chǎn)品的國(guó)內(nèi)醫(yī)療注冊(cè)認(rèn)證相關(guān)事宜
- 焦點(diǎn)播報(bào):南雄長(zhǎng)和物業(yè)擬轉(zhuǎn)讓南雄市壹城物業(yè)30%股權(quán) 底價(jià)30萬(wàn)元
- 全球信息:全國(guó)畜牧總站掛牌北京元立物業(yè)100%股權(quán) 轉(zhuǎn)讓底價(jià)為165萬(wàn)元
- 普利制藥:當(dāng)前公司生產(chǎn)及產(chǎn)能利用率情況正常,在建產(chǎn)能達(dá)到GMP標(biāo)準(zhǔn)的可使用狀態(tài)后公司將進(jìn)行商業(yè)化產(chǎn)投
- 每日快報(bào)!長(zhǎng)株潭煙草物流園100%股權(quán)及2.32億債權(quán)被掛牌 底價(jià)3.67億