成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

更優(yōu)的UI更新套路

移動(dòng)開(kāi)發(fā) Android
Android中的每個(gè)View的子類(lèi),都有超級(jí)多的set方法,比如TextView,就有setText,setTextColor等等。它就是每個(gè)set方法,實(shí)際上是給這個(gè)對(duì)象做一個(gè)數(shù)據(jù)上的變化,然后就不管了。等到系統(tǒng)來(lái)調(diào)用OnDraw方法的時(shí)候,在OnDraw方法中統(tǒng)一的來(lái)更新UI。

[[174789]]

之前有段時(shí)間寫(xiě)Windows桌面程序悟出的道理。

是這樣的,有時(shí)候,我們需要?jiǎng)?chuàng)建一個(gè)符合業(yè)務(wù)的View,或者稱為UI對(duì)象,比如,即時(shí)通訊軟件的好友列表里面的每個(gè)item,那么這個(gè)item要有頭像,名字,簡(jiǎn)短描述三個(gè)數(shù)據(jù)項(xiàng)。那么,我們這個(gè)View對(duì)象,就得有三個(gè)對(duì)應(yīng)的方法來(lái)設(shè)置這三個(gè)屬性,然后View顯示的時(shí)候,就顯示出我們***的數(shù)據(jù)就好了。

最最最開(kāi)始的時(shí)候,我都是耿直的寫(xiě)成這樣。

  1. // 以下是偽代碼的形式,并不嚴(yán)謹(jǐn) 
  2. class UserItemView extends View { 
  3.     ImageView mAvatar; 
  4.     TextView mName; 
  5.     TextView mDesc; 
  6.      
  7.     public void setAvatar(Bitmap avatarImage) { 
  8.         mAvatar.setImage(avatarImage); 
  9.     } 
  10.      
  11.     public void setName(String name) { 
  12.         mName.setText(name); 
  13.     } 
  14.      
  15.     public void setDesc(String desc) { 
  16.         mDesc.setText(desc); 
  17.     } 
  18.  

在最開(kāi)始的時(shí)候,這樣是OK的,看起來(lái)非常***,沒(méi)有任何問(wèn)題。如果某個(gè)用戶的數(shù)據(jù)變了,就更新某個(gè)數(shù)據(jù)就好了。

好,現(xiàn)在問(wèn)題了,這樣寫(xiě)的問(wèn)題在于,當(dāng)狀態(tài)/數(shù)據(jù)之間相互依賴對(duì)UI的顯示產(chǎn)生影響時(shí),那么就會(huì)出問(wèn)題,代碼會(huì)混亂。

我們現(xiàn)在提個(gè)這樣的需求,如果描述(desc)是空的,就顯示出頭像,如果不是空的,就不顯示頭像。

需求確實(shí)很奇怪,但是實(shí)際的工作中一定會(huì)遇到類(lèi)似的情況。

那么,首先我們想當(dāng)然的改動(dòng)一下代碼吧。

  1. class UserItemView extends View { 
  2.     ImageView mAvatar; 
  3.     TextView mName; 
  4.     TextView mDesc; 
  5.      
  6.     String mDescData; 
  7.      
  8.     public void setAvatar(Bitmap avatarImage) { 
  9.         mAvatar.setImage(avatarImage); 
  10.     } 
  11.      
  12.     public void setName(String name) { 
  13.         mName.setText(name); 
  14.     } 
  15.      
  16.     public void setDesc(String desc) { 
  17.         mDescData = desc
  18.         if (mDescData == null || mDescData .equals("")) { 
  19.             mAvatar.setVisible(true); 
  20.         } else { 
  21.             mAvatar.setVisible(false); 
  22.         } 
  23.         mDesc.setText(mDescData ); 
  24.     } 
  25.  

你看,現(xiàn)在設(shè)置描述的方法里要去管頭像的顯示情況,這就很惡心了。如果有更多的數(shù)據(jù)項(xiàng)和狀態(tài),更多的UI控件,他們之間有非常多的依賴關(guān)系,如果按這樣的寫(xiě)法,你的每個(gè)方法里面的邏輯都會(huì)變得非常惡心,復(fù)雜。甚至,設(shè)置某個(gè)UI的狀態(tài)還需要依賴其他的數(shù)據(jù)項(xiàng),你沒(méi)辦法,只能把無(wú)關(guān)的數(shù)據(jù)當(dāng)參數(shù)傳入,就會(huì)變成這樣。

  1. // !!!爆炸!!!為什么頭像要關(guān)注其他的數(shù)據(jù)!!! 
  2. public void setAvatar(Bitmap avatarImage, String desc) { 
  3.     mAvatar.setImage(avatarImage); 
  4.     if (desc== null || desc.equals("")) { 
  5.         mAvatar.setVisible(true); 
  6.     } else { 
  7.         mAvatar.setVisible(false); 
  8.     } 
  9.  

當(dāng)時(shí),我那個(gè)UI已經(jīng)變得非常惡心了,在這樣的情況下,我終于意識(shí)到,對(duì)UI對(duì)象的更新,不能就地去做,UI對(duì)象的更新,應(yīng)該用一個(gè)統(tǒng)一的方法來(lái)做,而會(huì)改變UI顯示情況的那些setXXXX方法,只做兩件事,一是把數(shù)據(jù)設(shè)到這個(gè)對(duì)象的成員屬性上,另一件事就是調(diào)用統(tǒng)一的方法來(lái)更新UI。

其實(shí)一個(gè)標(biāo)準(zhǔn)的設(shè)計(jì)一直在眼前,直到那一刻,我才意識(shí)到和真正的理解。那就是Android中的View。Android中的每個(gè)View的子類(lèi),都有超級(jí)多的set方法,比如TextView,就有setText,setTextColor等等。它就是每個(gè)set方法,實(shí)際上是給這個(gè)對(duì)象做一個(gè)數(shù)據(jù)上的變化,然后就不管了。等到系統(tǒng)來(lái)調(diào)用OnDraw方法的時(shí)候,在OnDraw方法中統(tǒng)一的來(lái)更新UI。

接下來(lái)就簡(jiǎn)單了。我們的代碼改成這樣:

  1. class UserItemView extends View { 
  2.     ImageView mAvatar; 
  3.     TextView mName; 
  4.     TextView mDesc; 
  5.      
  6.     String mNameData; 
  7.     String mDescData; 
  8.     Bitmap mAvatarData; 
  9.      
  10.     public void updateView() { 
  11.         mAvatar.setImage(mAvatarData); 
  12.         if (mDescData== null || mDescData.equals("")) { 
  13.             mAvatar.setVisible(true); 
  14.         } else { 
  15.             mAvatar.setVisible(false); 
  16.         } 
  17.          
  18.         mDesc.setText(mDescData); 
  19.          
  20.         mName.setText(mNameData); 
  21.     } 
  22.      
  23.     public void setAvatar(Bitmap avatarImage) { 
  24.         mAvatarData = avatarImage; 
  25.         updateView(); 
  26.     } 
  27.      
  28.     public void setName(String name) { 
  29.         mNameData = name
  30.         updateView(); 
  31.     } 
  32.      
  33.     public void setDesc(String desc) { 
  34.         mDescData = desc
  35.         updateView(); 
  36.     } 
  37.  

注意到,添加了一個(gè)updateView方法,這個(gè)方法專門(mén)用來(lái)將數(shù)據(jù)更新到UI上,這樣寫(xiě),其他set方法一律只做把數(shù)據(jù)存進(jìn)來(lái)的事情,updateView方法專門(mén)根據(jù)當(dāng)前的數(shù)據(jù)狀態(tài)更新UI,這樣set方法就干凈整潔。而邏輯再?gòu)?fù)雜的顯示邏輯,都不用怕,在updateView里面搞就行了。

我曾經(jīng)并且一直在維護(hù)的一個(gè)Activity,它大概有15+個(gè)View,20-30個(gè)數(shù)據(jù)和狀態(tài),這些數(shù)據(jù)和狀態(tài)會(huì)謎一般的印象著這些view的顯示。當(dāng)時(shí)年輕不懂事,就耿直的在數(shù)據(jù)變化的后面(下一行),立馬就更新UI的狀態(tài)。有如下這些位置吧:

  • 點(diǎn)擊事件
  • 系統(tǒng)回調(diào)
  • 網(wǎng)絡(luò)請(qǐng)求回調(diào)
  • 定時(shí)器,handler

這么多地方都在更新數(shù)據(jù),并且改變UI,維護(hù)起來(lái)簡(jiǎn)直要屎。

后來(lái),在我領(lǐng)悟到上面這個(gè)技巧后,我重構(gòu)了一波,里面有個(gè)超級(jí)大的updateView方法,然后對(duì)每個(gè)View進(jìn)行更新。

這里有另一個(gè)小技巧,就是你有1w個(gè)View,和1w個(gè)狀態(tài),你按狀態(tài)分類(lèi)寫(xiě),還是按View分類(lèi)寫(xiě)。這個(gè)意思就是:按正常人思維吧,比如你的頁(yè)面有兩種模式,一般人就會(huì)寫(xiě)

  1. if (mode == A) { 
  2.     viewA.xxxxxx 
  3.     viewB.xxxxxx 
  4.     ... 
  5. else if (mode == B) { 
  6.     viewA.xxxxxx 
  7.     viewB.xxxxxx 
  8.     ... 
  9.  

這樣寫(xiě)又出問(wèn)題了,少年,你以為你的狀態(tài)只有兩種嗎?你以為每個(gè)UI對(duì)象,就只依賴一個(gè)狀態(tài)嗎?會(huì)這么優(yōu)雅的剛好分布在if和else里面嗎?你錯(cuò)了,需求這個(gè)東西啊,是非常惡心的,完全不符合邏輯的。

這樣寫(xiě)呢,當(dāng)你狀態(tài)很多很多的時(shí)候,你很難去安排這個(gè)view的更新放哪里,如果有新加的狀態(tài)又影響到它。為了不影響到之前的邏輯,你往往就是再后面再加上一行,這樣多了也是難以維護(hù)的。

那樣怎么做呢?最簡(jiǎn)單,按View來(lái)分類(lèi)寫(xiě)。你有1w個(gè)View吧,那就挨個(gè)挨個(gè)來(lái),先把***個(gè)View處理好了,***個(gè)View受那些影響呢?全部寫(xiě)出來(lái),if-else也好,什么都好,反正最開(kāi)始這幾行代碼,先把View1搞定。

然后再一次寫(xiě)View2,View3的邏輯,這樣唯一的缺點(diǎn)就是,你的判斷得重復(fù)寫(xiě)。看上去很累贅,view1和view2,很可能他們的顯示邏輯是相同的,你非常想把他們寫(xiě)在一個(gè)if-else里,但是我建議你不要這么做,為了***的變通性,請(qǐng)將他們分開(kāi)寫(xiě)。

當(dāng)你日后維護(hù)的時(shí)候,哪個(gè)View出問(wèn)題了,你只要找到那一坨就好了,別的都不需要管。

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2012-04-27 09:38:05

jQuery UI

2019-03-18 10:02:16

緩存更新數(shù)據(jù)

2016-09-18 15:38:10

CMDB配置

2015-09-06 09:23:23

Android異步更新

2025-02-10 07:05:00

WinFormUI線程

2021-08-11 07:22:27

Vue 技巧 開(kāi)發(fā)工具

2024-10-24 17:13:55

WinformUI多線程

2023-12-21 10:26:30

??Prettier

2017-03-14 15:58:55

睿江云IDC機(jī)房安全

2022-05-13 08:48:50

React組件TypeScrip

2018-02-08 14:57:22

對(duì)象內(nèi)存分配

2017-08-14 16:12:56

面試套路原則

2021-06-28 05:25:26

Windows 11操作系統(tǒng)微軟

2018-08-24 13:55:05

2017-05-17 15:50:34

開(kāi)發(fā)前端react

2017-01-23 21:05:00

AndroidApp啟動(dòng)優(yōu)化

2018-07-12 14:20:33

SQLSQL查詢編寫(xiě)

2024-02-23 08:57:42

Python設(shè)計(jì)模式編程語(yǔ)言

2017-05-23 14:20:17

WebPython框架

2021-06-25 15:53:25

Kubernetes程序技巧
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 99久久精品视频免费 | 雨宫琴音一区二区在线 | 精品久久伊人 | 国产黄色av网站 | 国产精品99免费视频 | 黄色免费在线观看 | 国产人免费人成免费视频 | 日本三级电影免费观看 | 亚洲欧洲av在线 | 精品一区二区电影 | www.日本国产 | 欧美日韩国产一区二区 | 精品一区二区在线观看 | 国产亚洲一区二区三区 | 性一交一乱一透一a级 | 国产一区91精品张津瑜 | 亚洲精品一级 | 夏同学福利网 | 精品国产青草久久久久福利 | 亚洲成人动漫在线观看 | 国产高清在线精品 | 丁香五月缴情综合网 | www.亚洲一区二区 | 久久久久国产一级毛片高清网站 | 亚洲最大的黄色网址 | 狠狠干天天干 | 蜜桃av鲁一鲁一鲁一鲁 | www.亚洲视频 | 久久久久久久久久久蜜桃 | a国产一区二区免费入口 | 国产线视频精品免费观看视频 | 黄色在线免费观看 | 亚洲成人精品 | 91精品国产综合久久久动漫日韩 | 欧美综合一区 | 欧洲精品码一区二区三区免费看 | 中文字幕一区二区三区精彩视频 | 在线观看精品视频网站 | 国产高清视频在线观看播放 | 亚洲一二三区在线观看 | 国产在线观看福利 |