偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

提升Android ListView性能的幾個技巧

移動開發(fā) Android
ListView是設(shè)計應(yīng)用于對可擴展性和高性能要求的地方,意味著ListView有以下2個要求:1、盡可能少的創(chuàng)建View;2、只是繪制和布局在屏幕上可見的子View。

譯者注:

1. 由于這是技術(shù)文章,所以有些詞句使用原文,表達更準(zhǔn)確。

2. 由于水平有效,有些地方可能翻譯的不夠準(zhǔn)確,如有不當(dāng)之處,敬請批評指正;

3. inflation這個詞一直找不到特別好的中文翻譯。

ListView如何運作的?

ListView是設(shè)計應(yīng)用于對可擴展性和高性能要求的地方。實際上,這就意味著ListView有以下2個要求:

  1. 盡可能少的創(chuàng)建View;
  2. 只是繪制和布局在屏幕上可見的子View。

理解***點很簡單:通過布局xml文件在創(chuàng)建View并顯示是很昂貴耗時耗資源的操作。盡管布局文件已經(jīng)編譯打包成了二進制形式以便于更高效的語法解析,但是創(chuàng)建View仍然需要通過一個特殊的XML樹,并實例化所有需要響應(yīng)的View。

ListView通過回收一些不可見的Views,通常在Android源碼中稱為“ScrapView(廢棄的View)”來解決這個問題。這及意味著開發(fā)者只需要簡單的更新每行的內(nèi)容而不需要針對每個單獨的行的布局來創(chuàng)建View。

為了實現(xiàn)第二點,在我們滑動屏幕時,ListView通過使用View回收器來增加低于或者高于當(dāng)當(dāng)前窗口的Views,并當(dāng)前活動的Views移動到一個可回收池中。這樣的話,ListView只需要在內(nèi)存中保持足夠多的Views去填充分配空間中的布局和一些額外的可回收Views,即使當(dāng)你的Adapter有上百個items的適合。它會使用不同的方法去填充行之間的空間,從頂部或者底部等等,具體取決于窗口是如何變化的。

下面這個圖很直觀的展示了當(dāng)你按下ListView的時候發(fā)生了什么:

ListView

通過上述介紹,相比我們已經(jīng)熟悉了ListView的這種機制,讓我們繼續(xù)前往技巧部分。正如上述介紹的,在滑動時,ListView通過動態(tài)的創(chuàng)建和回收很多View,實現(xiàn)了盡可能地讓Adapter的getView()輕量。所有的技巧都是通過多種方法讓getView()更快。

View的回收

當(dāng)ListView每次需要在屏幕上顯示新的一行的時候,會從其Adapter中調(diào)用getView()的方法。眾所周知,getView()方法有3個參數(shù):行的位置, convertView以及父ViewGroup。

參數(shù)convertView說穿來就是之前講述的ScrapView。當(dāng)ListView要求更新一行的布局時,convertView是一個非空值。因此,當(dāng)convertView值非空時,你僅僅需要更新內(nèi)容即可,而不需要重新一個新行的布局。getView()在Adapter中一般是如下的形式:

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.     if (convertView == null) { 
  3.         convertView = mInflater.inflate(R.layout.your_layout, null); 
  4.     } 
  5.  
  6.     TextView text = (TextView) convertView.findViewById(R.id.text); 
  7.     text.setText("Position " + position); 
  8.  
  9.     return convertView; 

View Holder如何寫的模板

Android很常見的一個操作就是在布局文件中找到一個內(nèi)部的View。通常是使用一個findViewById()的View方法來實現(xiàn)的。這個findViewById()方法在View樹中,根據(jù)一個View ID,會遞歸的被調(diào)用來找到其子樹。雖然在靜態(tài)UI布局中使用findViewById()是完全正常的。但是,在滑動時,ListView調(diào)用其Adapter中的getView()是非常頻繁的。findViewById()可能會影響ListView滑動時的性能,尤其是你的行布局是很復(fù)雜的時候。

尋找一個充氣布局內(nèi)的內(nèi)部觀點是在Android上最常用的操作之一。這通常是通過一個名為findViewById(查看方法完成)。此方法將遞 歸經(jīng)過視圖樹尋找一個孩子用給定的ID碼。靜態(tài)的UI布局使用findViewById()是完全正常,但正如你所看到的,ListView中滾動時調(diào)用 適配器的getView()非常頻繁。 findViewById()可能perceivably擊中ListViews,尤其是滾動的性能,如果你行的布局是不平凡的。

View Holder的模式就是減少在Adapter中g(shù)etView()方法中調(diào)用findViewById()次數(shù)。實際上,View Holder是一個輕量級的內(nèi)部類,用于直接引用到所有內(nèi)部views。在創(chuàng)建View之后,你可以在每行的View存儲為一個標(biāo)簽。通過這種方法,只需要在初次創(chuàng)建布局的時候調(diào)用findViewById()。下面是一個使用上述方法的View Holder模板的代碼示例:

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.     ViewHolder holder; 
  3.  
  4.     if (convertView == null) { 
  5.         convertView = mInflater.inflate(R.layout.your_layout, null); 
  6.  
  7.         holder = new ViewHolder(); 
  8.         holder.text = (TextView) convertView.findViewById(R.id.text); 
  9.  
  10.         convertView.setTag(holder); 
  11.     } else { 
  12.         holder = convertView.getTag(); 
  13.     } 
  14.  
  15.     holder.text.setText("Position " + position); 
  16.  
  17.     return convertView; 
  18.  
  19. private static class ViewHolder { 
  20.     public TextView text; 

異步加載

很多時候,Android應(yīng)用在ListView每行中顯示一些多媒體內(nèi)容,比如圖片等。在Adapter中的getView()使用應(yīng)用內(nèi)置的圖片資源還是不會出什么問題的,因為可以存儲在Android的高速緩存中。但當(dāng)你想多態(tài)的顯示來自本地磁盤或網(wǎng)絡(luò)的內(nèi)容時,例如縮略圖,簡歷圖片等。在這種情況下,你可能不希望直接在Adapter中的getView()加載它們,因為IO進程會阻塞UI線程。如果這樣做的話,ListView就看起來非常卡頓。

在一個單獨的線程,如果想要運行的所有行的IO操作或任何高負(fù)載CPU限制的異步操作。其中的技巧就是要做到符合ListView的回收行為。例如,如果在Adapter中的getView()中,使用AsyncTask的加載去加載資料圖片,在AsyncTask完成之前,你正在加載的圖片View就有可能被回收用于其他地方。所以,一旦異步操作完成的同時,需要一種機制來知道如果相應(yīng)的View有沒有被回收。

一個簡單的方法來實現(xiàn)這一目標(biāo)是通過附加一些標(biāo)識該行與它相關(guān)的View的信息。然后,當(dāng)異步操作完成的適合,檢查目標(biāo)行的View和標(biāo)識的View是否一致。實現(xiàn)這一目標(biāo)的方法很多。下面是實現(xiàn)這種方法的一個很簡單的示例:

  1. public View getView(int position, View convertView, 
  2.         ViewGroup parent) { 
  3.     ViewHolder holder; 
  4.  
  5.     ... 
  6.  
  7.     holder.position = position; 
  8.  
  9.     new ThumbnailTask(position, holder) 
  10.             .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null); 
  11.  
  12.     return convertView; 
  13.  
  14. private static class ThumbnailTask extends AsyncTask { 
  15.     private int mPosition; 
  16.     private ViewHolder mHolder; 
  17.  
  18.     public ThumbnailTask(int position, ViewHolder holder) { 
  19.         mPosition = position; 
  20.         mHolder = holder; 
  21.     } 
  22.  
  23.     @Override 
  24.     protected Cursor doInBackground(Void... arg0) { 
  25.         // Download bitmap here 
  26.     } 
  27.  
  28.     @Override 
  29.     protected void onPostExecute(Bitmap bitmap) { 
  30.         if (mHolder.position == mPosition) { 
  31.             mHolder.thumbnail.setImageBitmap(bitmap); 
  32.         } 
  33.     } 
  34.  
  35. private static class ViewHolder { 
  36.     public ImageView thumbnail; 
  37.     public int position; 

人機交互知識

做到在每一行異步加載很多資源,是一個高性能的ListView的必經(jīng)之路。但是,在滑動屏幕時,如果你一味的在每一個getView()調(diào)用里面都去啟動一個異步的操作,造成的結(jié)果就是你會浪費大量資源。因為行被頻繁回收,造成大部分返回的結(jié)果會被丟棄。

考慮到實際的人機交互情況,在ListView適配器中,在每一行中都不應(yīng)該去觸發(fā)任何異步操作。也就是說,在ListView中有fling(快速滑動)操作時,啟動任何異步操作都沒有任何意義。一旦滾動停止或即將停止,才是開始真正顯示每行的內(nèi)容的時候。

我不會發(fā)布一個代碼示例貼在這里,因為其中涉及到的代碼太多。Romain Guy寫了一個很經(jīng)典的應(yīng)用:Shelves app,其中有一個很好的的示例。當(dāng)GridView停止滑動時不做其他事情時,它就開始觸發(fā)從而去異步加載書的封面資源。即使在滑動時,你也可以展示緩存中的內(nèi)容,通過使用memory cache來平衡交互。這真是個好主意!

以上

我強烈推薦你看下Romain Guy和Adam Powell的關(guān)于ListView的討論,里面涵蓋了很多這篇文章的東西。你可以看看Pattrn,可以看到這里面的幾個技巧是如何在應(yīng)用中運用的。

希望它是你在Android開發(fā)中一個很有用的參考:–)

Long Luo at PM17:30 Feb. 14th, 2014 @Shenzhen, China.

original link:http://longluo.github.io/blog/20140214/some_tips_about_android_listview_performence/

 written by Frank Luo posted at http://longluo.github.io

翻譯 Long Luo

原文鏈接:Performance Tips for Android’s ListView

責(zé)任編輯:閆佳明 來源: longluo.github.io
相關(guān)推薦

2024-11-15 10:45:56

2022-07-18 08:08:16

Go?語言技巧

2021-05-11 12:30:21

PyTorch代碼Python

2011-07-05 14:59:17

java

2011-10-19 10:08:01

AndroidListView

2024-06-11 00:09:00

JavaScript模式變量

2015-02-05 09:47:52

Web性能Web開發(fā)

2024-11-18 19:00:29

2010-06-18 09:17:51

jQuery

2021-10-14 07:55:17

提示技巧C#

2023-09-26 12:02:34

C++循環(huán)

2023-10-10 18:24:46

PostgreSQL性能RDBMS

2009-07-10 10:57:10

SSAS

2022-05-18 10:56:58

Java字符串編碼

2024-01-02 18:01:12

SQLSELECT查詢

2009-06-29 19:13:54

VMware ESX虛擬化虛擬機

2017-11-06 14:33:54

Web開發(fā)服務(wù)器網(wǎng)絡(luò)

2022-11-04 11:18:16

代碼優(yōu)化可讀性

2023-12-01 15:54:44

2023-10-17 14:35:22

人工智能AI
點贊
收藏

51CTO技術(shù)棧公眾號