標籤:
上周開始直到昨天,我和我的同事遇到了一個不大不小的bug。不多說先敘述一下:
產品需求:
是一個專輯頁面,將優秀的,點擊量高的文章做成一個專輯,方便大家閱讀。就是一個listview,item有圖的顯示圖,沒圖就不顯示,但每個item都會有標題,有描述。有headerview,是這個專輯的標題和描述,也會有背景圖,還有對專輯的收藏按鈕和評論顯示,點擊收藏,按鈕變色,點擊評論,進入評論頁面;有footerview,做一些其他專輯的推薦。相信經過我這樣的描述,你的腦海中已經大致有了一個關於這樣專輯的布局印象,這裡我就不貼代碼了。
出現問題:
為什麼我對收藏和評論講的很詳細,因為問題就出現在了這裡。
進入專輯頁面後,當我點擊收藏時,第一次是可以點擊的並提示“已收藏”,當我再點擊時,就不再響應點擊事件了,注意,連點擊事件都不響應了,就更別提以後的那些邏輯了。
點擊評論按鈕進入評論頁面和它一樣,也是點一次好使,第二次就不好使了。而且二者都是在不好使(不響應點擊事件)之後,你點多少次都是白搭,都是不會響應,停在那裡。但是只要你一滑動頁面,無論滑動多麼小的一點距離,剛才不響應的點擊事件就會都響應出來,收藏僅僅是變色一次,而評論頁面,你剛才點擊多少次,它就會開啟多少次。
分析問題:
把我們遇到的在網上一搜,發現類似問題還真不少,致使開始我們也以為是listview的item和button搶奪焦點問題,就xml上添加了幾個屬性,沒有解決。
後來把點擊事件加在listview的item上,發現響應,加在headerview上就是不相應,以為是布局的問題,因為我們的布局中有個incloud,我們就把incloud裡面的內容提出來,沒有解決。
又開始懷疑事件傳遞,將相關的都返回了fasle,發現還是不行。並在這一階段發現每點擊一次的時候,listview都要getview(),按理說,圖片都已經down下來了,不應該,除非他重新計算位置。
深究getview()方法,在網上找到了這一篇,終於解決問題。很鬱悶,弄了一溜八開的,竟然僅僅是個布局問題,而不是代碼問題,更不是高大上的事件分法、線程同步的問題。記下了。現附上,部落格地址http://www.cnblogs.com/manuosex/p/3426160.html
引用部落格中的“
這是什麼樣的情況了,看了網上的資料以後我知道原來沒有設定器listview 的布局方式不是fill-parent,而是wrap-content,會計算父控制項的高度所以造成了一種反覆調用情況,從而次數不確定。
更深層次的解釋為:
View在Draw的時候分成兩個階段:measure和layout,在measure階段時主要就是為了計算兩個參數:height和width。而且要注意的是,這是個遞迴的過程,從頂向下,DecorView開始依次調用自己子項目的measure。計算完成這兩個參數後就開始layout,最後再是draw的調用。
對於ListView,當然每一個Item都會被調用measure方法,而在這個過程中getView和getCount會被調用,而且看使用者的需求,可能會有很多次調用。
而為什麼會有很多組次調用呢?
問題就在於在layout中的決定ListView或者它的父元素的height和width屬性的定義了。fill_parent會好一點,計算方法會比較簡單,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能給View當飯吃,還是要計算出來具體的dip,所以measure還是會被調用,只是可能比wrap_content的少一點。至於自適應的它會一直考量它的寬和高,根據內容(也就是它的子Item)計算寬高。可能這個measure過程會反覆執行,如果父元素也是wrap_content,這個過程會更加漫長。
所以,解決方案就是盡量避免自適應,除非是萬不得已,固定大小或者填充的效果會比較好一些。
”
android的listview中getview()的問題