国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android ListView列表控件的介紹和性能優(yōu)化

2019-10-22 18:35:12
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

ListView列表控件

一、ListView顯示數(shù)據(jù)的原理:mvc模式

m:mode 數(shù)據(jù)(用javabean規(guī)范封裝)

v:view ListView

c:adapter 適配器,負(fù)責(zé)把數(shù)據(jù)展示到ListView上

二、ListView最常用適配器

BaseAdapter、SimpleAdapter、ArrayAdapter

三、ListView顯示數(shù)據(jù)的步驟

1.創(chuàng)建ListView

2.自定義ListView的適配器繼承BaseAdapter,重寫baseAdapter的getCount方法和getView方法

3.創(chuàng)建自定義ListView的適配器

4.ListView設(shè)置適配器:listView.setAdapter(adapter);

private class ListViewAdapter extends BaseAdapter{    //返回需要展示的數(shù)據(jù)的條數(shù)    @Override    public int getCount() {      return 200;    }    //返回指定position位置對(duì)應(yīng)的數(shù)據(jù)對(duì)象,一般很少用    @Override    public Object getItem(int position) {      return null;    }    //返回position位置對(duì)應(yīng)id    @Override    public long getItemId(int position) {      return 0;    }    /**     * 獲取一個(gè)view,會(huì)作為listview的第position個(gè)item條目出現(xiàn),用來(lái)顯示listview的數(shù)據(jù)     *      * @param convertView 歷史緩存對(duì)象     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {      View view ;      if (convertView == null) {        //創(chuàng)建新的View對(duì)象         view = View.inflate(MainActivity.this, R.layout.listview_item,null);      }else{        //復(fù)用歷史緩存View對(duì)象        view = convertView;      }      TextView tv=(TextView)view.findViewById(R.id.tv);      tv.setText("item:" + position);      return view;    }        }

四、ListView的性能優(yōu)化

1.ListView的奇怪現(xiàn)象

問(wèn)題:

如果ListView的高度設(shè)為包裹內(nèi)容,getView方法會(huì)多次調(diào)用

android,listview,列表控件

原因:

如果height設(shè)為”wrap_content”,為了把所有條目都顯示出來(lái),會(huì)多次校驗(yàn)數(shù)據(jù)是否可在屏幕顯示完,(校驗(yàn)1次不保準(zhǔn),再多次校驗(yàn))將多次調(diào)用getView方法

解決:以后再使用ListView的時(shí)候,高度設(shè)置為填充父窗體 android:layout_height=”match_parent”

2.避免內(nèi)存溢出優(yōu)化:ListView復(fù)用歷史緩存View對(duì)象

問(wèn)題:如果不復(fù)用歷史緩存View對(duì)象,當(dāng)ListView的條目數(shù)過(guò)多,向下滑的很深時(shí),會(huì)報(bào)錯(cuò)。

報(bào)錯(cuò)信息: E/dalvikvm-heap(2636): Out of memory on a -294967280-byte allocation. 內(nèi)存溢出

原因:不停創(chuàng)建新的View,消耗內(nèi)存。為每一個(gè)Item都創(chuàng)建一個(gè)View對(duì)象,必將占用很多內(nèi)存空間。從xml中生成View,這是屬于IO操作,是耗時(shí)操作,所以必將影響性能

解決:可以對(duì)消失在屏幕的View進(jìn)行緩存,當(dāng)往下拖動(dòng)時(shí)復(fù)用歷史緩存,這樣就只創(chuàng)建屏幕能顯示的View個(gè)數(shù)的數(shù)量的View。getView方法有個(gè)參數(shù)convertView就是可以復(fù)用的歷史緩存View對(duì)象。這個(gè)對(duì)象也可能為空,當(dāng)它為空的時(shí)候,表示該條目view第一次創(chuàng)建,所以我們需要inflate一個(gè)view出來(lái)。

原理:Android提供了一個(gè)叫做Recycler(反復(fù)循環(huán))的構(gòu)件,就是當(dāng)ListView的Item從滾出屏幕視角之外,對(duì)應(yīng)Item的View會(huì)被緩存到Recycler中,相應(yīng)的會(huì)從生成一個(gè)Item,而此時(shí)調(diào)用的getView中的convertView參數(shù)就是滾出屏幕的緩存Item的View,所以說(shuō)如果能重用這個(gè)convertView,就會(huì)大大改善性能。

public View getView(int position, View convertView, ViewGroup parent) { TextView tv; if (convertView == null) { // 創(chuàng)建新的view 對(duì)象 tv = new TextView(MainActivity.this); System.out.println(“創(chuàng)建新的view對(duì)象—” + position); } else { System.out.println(“復(fù)用歷史緩存對(duì)象—” + position); view = (TextView) convertView; } tv.setText(“4月14日科比告別戰(zhàn)倒計(jì)時(shí):” + position); return tv; }

3.item子控件顯示卡頓優(yōu)化:ViewHolder重用機(jī)制

問(wèn)題:item中的子控件很多時(shí)加載慢。findViewById是到xml文件中去查找對(duì)應(yīng)的id,可以想象如果組件多的話也是挺費(fèi)事的,如果我們可以讓view內(nèi)的組件也隨著view的復(fù)用而復(fù)用,那該是多美好的一件事。

原因:在getView()方法中的操作是先從xml中創(chuàng)建view對(duì)象(inflate操作,我們采用了重用convertView方法優(yōu)化),然后在這個(gè)view去findViewById,找到每一個(gè)item的子View的控件對(duì)象,如:ImageView、TextView等。這里的findViewById操作是一個(gè)樹(shù)查找過(guò)程,也是一個(gè)耗時(shí)的操作。

解決:谷歌推薦了一種優(yōu)化方法來(lái)做應(yīng)對(duì),那就是重新建一個(gè)內(nèi)部靜態(tài)類,里面的成員變量跟view中所包含的組件個(gè)數(shù)類型相同

private static class ViewHolder {}

基本思路就是在convertView為null的時(shí)候,我們不僅重新inflate出來(lái)一個(gè)view,并且還需要進(jìn)行findviewbyId的查找工作,但是同時(shí)我們還需要獲取一個(gè)ViewHolder類的對(duì)象,并將findviewById的結(jié)果賦值給ViewHolder中對(duì)應(yīng)的成員變量。最后將holder對(duì)象與該view對(duì)象“綁”在一塊。當(dāng)convertView不為null時(shí),我們讓view=converView,同時(shí)取出這個(gè)view對(duì)應(yīng)的holder對(duì)象,就獲得了這個(gè)view對(duì)象中的子控件,就是holder中的成員變量,這樣在復(fù)用的時(shí)候,我們就不需要再去findViewById了,只需要在最開(kāi)始的時(shí)候進(jìn)行數(shù)次查找工作就可以了。這里的關(guān)鍵在于如何將view與holder對(duì)象進(jìn)行綁定,那么就需要用到兩個(gè)方法:View中的setTag和getTag方法了。

經(jīng)過(guò)上面的做法,可能大家感覺(jué)不太到優(yōu)化的效果,根據(jù)Google的文檔,實(shí)際優(yōu)化效果在百分之5左右。

4.網(wǎng)絡(luò)數(shù)據(jù)過(guò)多加載緩慢優(yōu)化

問(wèn)題:

ListView如果顯示本地的List集合中的內(nèi)容,List的長(zhǎng)度也只有100個(gè),我們可以毫不費(fèi)力一次性加載完這100個(gè)數(shù)據(jù);但是實(shí)際應(yīng)用中,我們往往會(huì)需要使用Listview來(lái)顯示網(wǎng)絡(luò)上的內(nèi)容,比如說(shuō)我們拿使用ListView顯示新聞為例:假如網(wǎng)絡(luò)情況很好,我們使用的手機(jī)也許能夠一下子加載完所有新聞數(shù)據(jù),然后顯示在ListView中,用戶可能感覺(jué)還好,假如說(shuō)在網(wǎng)絡(luò)不太順暢的情況下,用戶加載完所有網(wǎng)絡(luò)的數(shù)據(jù),可能這個(gè)list是1000條新聞,那么用戶可能需要面對(duì)一個(gè)空白的Activity好幾分鐘,這個(gè)顯然是不合適的。

解決:

我們需要進(jìn)行分批加載,比如說(shuō)1000條新聞的List集合,我們一次加載20條,等到用戶翻頁(yè)到底部的時(shí)候,我們?cè)偬砑酉旅娴?0條到List中,再使用Adapter刷新ListView,這樣用戶一次只需要等待20條數(shù)據(jù)的傳輸時(shí)間,不需要一次等待好幾分鐘把數(shù)據(jù)都加載完再在ListView上顯示。其次這樣也可以緩解很多條新聞一次加載進(jìn)行產(chǎn)生OOM應(yīng)用崩潰的情況。

5.加載數(shù)據(jù)過(guò)多內(nèi)存溢出優(yōu)化

問(wèn)題:

我們知道Android虛擬機(jī)給每個(gè)應(yīng)用分配的運(yùn)行時(shí)內(nèi)存是一定的,一般性能不太好的機(jī)器只有16M,好一點(diǎn)的可能也就是64M的樣子,假如說(shuō)我們現(xiàn)在要瀏覽的新聞總數(shù)為一萬(wàn)條,即便是網(wǎng)絡(luò)很好的情況下,我們可以很快的加載完畢,但是多數(shù)情況下也會(huì)出現(xiàn)內(nèi)存溢出從而導(dǎo)致應(yīng)用崩潰的情況。

解決:

實(shí)際上,分批加載也不能完全解決問(wèn)題,因?yàn)殡m然我們?cè)诜峙幸淮沃辉黾?0條數(shù)據(jù)到List集合中,然后再刷新到ListView中去,假如有10萬(wàn)條數(shù)據(jù),如果我們順利讀到最后這個(gè)List集合中還是會(huì)累積海量條數(shù)的數(shù)據(jù),還是可能會(huì)造成OOM的情況,這時(shí)候我們就需要用到分頁(yè),比如說(shuō)我們將這10萬(wàn)條數(shù)據(jù)分為1000頁(yè),每一頁(yè)100條數(shù)據(jù),每一頁(yè)加載時(shí)都覆蓋掉上一頁(yè)中List集合中的內(nèi)容,然后每一頁(yè)內(nèi)再使用分批加載,這樣用戶的體驗(yàn)就會(huì)相對(duì)好一些。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 上思县| 封开县| 额敏县| 家居| 林芝县| 忻城县| 延津县| 横峰县| 临安市| 鄱阳县| 枞阳县| 蒲江县| 皮山县| 于田县| 上蔡县| 绥中县| 丹阳市| 保亭| 雷州市| 凤台县| 印江| 宜城市| 金阳县| 巴彦淖尔市| 岳西县| 金川县| 布拖县| 太保市| 清新县| 武乡县| 化德县| 高平市| 雷波县| 登封市| 汝阳县| 河池市| 白水县| 五台县| 曲沃县| 南华县| 岫岩|