部分內(nèi)容參考了[大天使H5主程死肥仔在LAYA沙龍的演講PPT]我抠,感謝主程陳策的無私分享!
另外參考極光會客廳:大型H5游戲如何登陸微信小游戲及游戲性能優(yōu)化分享
一搞疗、分析工具
1.laya.utils.Stat性能統(tǒng)計面板介紹
2.使用chrome的性能分析器
二断国、內(nèi)存優(yōu)化
參考內(nèi)存優(yōu)化方式
1.對象池Laya.utils.Pool
當對象設(shè)置為null,不會立即將其從內(nèi)存中刪除渔欢。只有系統(tǒng)認為內(nèi)存足夠低時,垃圾回收器才會運行瘟忱。內(nèi)存分配(而不是對象刪除)會觸發(fā)垃圾回收奥额。
垃圾回收期間可能占用大量CPU并影響性能。通過重用對象酷誓,嘗試限制使用垃圾回收披坏。此外,盡可能將引用設(shè)置為null盐数,以便垃圾回收器用較少時間來查找對象棒拂。有時(比如兩個對象相互引用),無法同時設(shè)置兩個引用為null玫氢,垃圾回收器將掃描無法被訪問到的對象帚屉,并將其清除,這會比引用計數(shù)更消耗性能漾峡。
2.Handler.create使用了內(nèi)置對象池管理攻旦,因此在使用Handler對象時可使用Handler.create來創(chuàng)建回調(diào)處理器。
3.從內(nèi)存中清理資源
關(guān)于clearRes和clearTextureRes生逸,可以參考Texture資源銷毀和Laya Image graphics
比如UI上的資源牢屋,我是做成界面關(guān)閉一段時間后且预,該界面沒有被再次打開,說明這個界面不是個需求常被打開的界面烙无,就可以刪除他的資源了锋谐。但資源有可能是多界面共用的,所以我還會判斷是否被其他界面使用截酷。沒有其他界面使用的涮拗,就可以刪除了。
UI上的動畫迂苛,動畫是多幀的三热,占的資源會比較多。而且動畫一般是做提示作用三幻,顯示一次會再打開該界面就漾,也許就不需要該動畫了。所以我是對動畫處理成關(guān)閉界面后赌髓,如果沒有其他界面正在使用該資源空闲,就立即刪除該資源蝴猪。
對于怪和其他玩家,原來我是做切地圖的時候才清除的蒿辙,因為我們一張地圖里的怪的種類是有限的懊蒸。但后來內(nèi)存還是太大了荣倾,IOS有點頂不住,所以后來改成每個怪被殺后骑丸,判斷它的資源有沒有其他怪也正在使用舌仍,沒有的話就刪除⊥ㄎ#基本上就是這一波同種類的怪全被殺掉后铸豁,就會清除資源。這里說下菊碟,這些資源除了圖片外节芥,還包括聲音
角色是游戲是主角,他們的動作會比較多逆害,每個動作都會是一份資源头镊。如果按怪和其他玩家的資源刪除規(guī)則肯定是不科學的。我是給每個角色做了資源的列表魄幕,但某個動作的資源一段時間沒有使用相艇,說明這個動作不是常播放的動作,就可以刪除了纯陨。技能動畫坛芽,技能本質(zhì)上其實和主角的動作資源是類似的留储,所以也是記錄一段時間內(nèi)沒有再次被使用,就會被刪除咙轩。
把不用的資源都刪除了欲鹏,內(nèi)存占用還會高,那最直接的方法就是減小資源的大小臭墨。比如我們可以把某個圖縮小赔嚎,再在程序里把他放大,這樣內(nèi)存占用會小胧弛,表現(xiàn)上會差不多尤误,就是圖有可能會糊一些。
對于主角结缚,他是游戲視覺的中心损晤,玩家會一起盯著他,所以我不對主角的資源進行縮小红竭∮妊縮小會影響到游戲的品質(zhì)。對于游戲里的怪茵宪,他們不是視覺的中心最冰,我們把他縮小到原圖的67%,再在游戲里放大稀火,為什么是67%呢暖哨,因為這樣的話在程序里scale設(shè)置為1.5就是原設(shè)計的尺寸了。
技能一般會比較大凰狞,但每一幀的變化也大篇裁,在游戲里一閃而過,玩家還沒看清會一閃而過了赡若,而且一般同一個技能的顏色也會比較統(tǒng)一达布,所以可以縮得更小一些,按技能的資源可以縮到一半甚至四分之一逾冬。比如黍聂,技能= 25% or 50%,武器= 67%粉渠,翅膀= 67%
4.關(guān)于濾鏡分冈、遮罩
嘗試盡量減少使用濾鏡效果。將濾鏡(BlurFilter和GlowFilter)應(yīng)用于顯示對象時霸株,運行時將在內(nèi)存中創(chuàng)建兩張位圖雕沉。其中每個位圖的大小與顯示對象相同。將第一個位圖創(chuàng)建為顯示對象的柵格化版本去件,然后用于生成應(yīng)用濾鏡的另一個位圖
當修改濾鏡的某個屬性或者顯示對象時坡椒,內(nèi)存中的兩個位圖都將更新以創(chuàng)建生成的位圖扰路,這兩個位圖可能會占用大量內(nèi)存。此外倔叼,此過程涉及CPU計算汗唱,動態(tài)更新時將會降低性能。
ColorFiter在Canvas渲染下需要計算每個像素點丈攒,而在WebGL下的GPU消耗可以忽略不計哩罪。
最佳的做法是,盡可能使用圖像創(chuàng)作工具創(chuàng)建的位圖來模擬濾鏡巡验。避免在運行時中創(chuàng)建動態(tài)位圖际插,可以幫助減少CPU或GPU負載。特別是一張應(yīng)用了濾鏡并且不會在修改的圖像显设。
5.圖片尺寸最好是2的整數(shù)冪
這個按鈕所用的資源是這樣的框弛,它的大小的是138×305。在手機里捕捂,圖片上傳到顯存后瑟枫,寬高會變成2的整數(shù)次冪,看圖片上的輔助線指攒,一個格子就是256×256的慷妙,所以這張圖片就會加大成256×512,如果我把圖片縮小成右邊這個大小幽七,那在顯存里景殷,就是128×256,比原來小了3/4澡屡。在這里,目的就是把正好大于2的整數(shù)次冪的圖咐旧,縮小一下變成2的整數(shù)次冪以內(nèi)驶鹉,可以少很多顯存。同樣的铣墨,一個圖集室埋,也有可能會有這樣的情況,也可以對里邊的一些散圖縮小伊约,或者換到別的圖集的方式讓他保持在2的整數(shù)次冪內(nèi)姚淆。
6.不在顯示區(qū)域內(nèi)的對象不加載
這是我們游戲的主城地圖,中間紅色框的部分是游戲顯示的區(qū)域屡律,黃色的是顯示區(qū)域腌逢,也就是角色,NPC等對象在黃色區(qū)域內(nèi)才會顯示超埋,在外邊的搏讶,就會不加載不顯示佳鳖,這里不單單是要記錄Visible為false,還要設(shè)置為不加載他當前的動作媒惕。為什么黃色區(qū)域會大于游戲顯示區(qū)域呢系吩。因為人物的位置一般是腳下的一個點,這個點出到屏幕外時妒蔚,他可能還有一半的身體還是需要顯示的穿挨。所以會留出一部分區(qū)域。細心的話你們可以看上邊的會留得比較小肴盏,因為是人物腳底為中心絮蒿,所以肢底以下還會顯示的部分會比較小。
三叁鉴、渲染優(yōu)化
參考圖形渲染性能
1.優(yōu)化Sprite
- 盡量減少不必要的層次嵌套土涝,減少Sprite數(shù)量。
- 非可見區(qū)域的對象盡量從顯示列表移除或者設(shè)置visible=false幌墓。當我們打開一個界面的時候但壮,玩家的視覺焦點會集中在打開的界面上,對于界面旁邊的東西常侣,并不會太去關(guān)注了蜡饵。所以,大家有沒有發(fā)現(xiàn)場景里的人物已經(jīng)不見了胳施?在彈出界面的時候溯祸,把人物,技能特效等隱藏掉舞肆,可以減少drawcall焦辅。這里要注意的是,隱藏只需要把角色的visable設(shè)置為false就可以達到減少drawcall椿胯。當然對于已經(jīng)隱藏掉的人筷登,不再去加載他切換動作的新動作資源,也是一個優(yōu)化點
- 對于容器內(nèi)有大量靜態(tài)內(nèi)容或者不經(jīng)常變化的內(nèi)容(比如按鈕)哩盲,可以對整個容器設(shè)置cacheAs屬性前方,能大量減少Sprite的數(shù)量,顯著提高性能廉油。如果有動態(tài)內(nèi)容惠险,最好和靜態(tài)內(nèi)容分開,以便只緩存靜態(tài)內(nèi)容抒线。
- Panel內(nèi)班巩,會針對panel區(qū)域外的直接子對象(子對象的子對象判斷不了)進行不渲染處理,超出panel區(qū)域的子對象是不產(chǎn)生消耗的十兢。
2.優(yōu)化DrawCall
- 對復雜靜態(tài)內(nèi)容設(shè)置cacheAs趣竣,能大量減少DrawCall摇庙,使用好cacheAs是游戲優(yōu)化的關(guān)鍵。
- 盡量保證同圖集的圖片渲染順序是挨著的遥缕,如果不同圖集交叉渲染卫袒,會增加DrawCall數(shù)量。
- 盡量保證同一個面板中的所有資源用一個圖集单匣,這樣能減少提交批次夕凝。
用LayaAir編輯好UI界面,可以在層級窗體里看到界面里的子對象户秤,大家注意看每一個子對象前邊码秉,都有一個小圓點,這個圓點的顏色代表了他來自哪個圖集鸡号,相同顏色的圓點代表是同一個圖集转砖。對于渲染來說,連續(xù)渲染相同圖集里的圖鲸伴,只會調(diào)用一次drawcall府蔗,所以在制作界面的時候,在不影響界面的情況下汞窗,把界面里各元件的層級調(diào)整一下姓赤,可以達到減少drawcall的目的。
這里要說一下不铆,程序字在游戲里,是會單個字生成圖片繪制在動態(tài)圖集里裹唆,所以程序字是同一個圖集的誓斥。把所有的文字統(tǒng)一放在界面最上邊也就是這個列表的最下邊,就可以減少drawcall品腹。當然岖食,這個操作不是可以想移就移的,要看要移動的子元件之前是否有前后關(guān)系
角色一般都會有一個影子舞吭,在我們游戲里影子不是做在角色的圖片上的,而是單獨立出來的一張圖析珊。為了方便操作羡鸥,我們一般會把人物的圖片和影子的圖片放到一個容器里,每一個容器就是一個角色忠寻。那場景里有兩個角色的時候惧浴,那這幾個圖片的順序就是:影子、角色A奕剃、影子衷旅、角色B捐腿。那就是四個drawcall,如果有N個角色柿顶,就有N*2個Drawcall茄袖。兩個角色的影子是同一張圖,一定是同一個圖集的嘁锯。那我們就可以優(yōu)化下宪祥。如果把所有角色的影子放在一個容器里,這個容器在所有角色的下邊家乘。那順序就是:影子蝗羊、影子、角色A仁锯、角色B耀找,那就是三個drawcall。如果是N個角色业崖,就是N+1個drawcall野芒。是不是就可以減少Drawcall了呢。當然腻要,如果要這么做复罐,邏輯就要改得比較復雜,因為要在移動人物的時候雄家,隱藏人物的時候效诅,人物變成半透明的時候,移除人物的時候趟济,都要同時控制影子乱投。我們可以在角色類里加入這些支持。同理顷编,角色頭上的名字戚炫、血條都要單獨放在一層里。
3.關(guān)于CacheAs
參考CacheAs靜態(tài)緩存優(yōu)化
cacheAs主要通過兩方面提升性能媳纬。一是減少節(jié)點遍歷和頂點計算双肤;二是減少drawCall。善用cacheAs將是引擎優(yōu)化性能的利器钮惠。設(shè)置cacheAs后茅糜,還可以設(shè)置staticCache=true以阻止自動更新緩存,同時可以手動調(diào)用reCache方法更新緩存素挽。
在對Canvas優(yōu)化時蔑赘,我們需要注意,在以下場合不要使用cacheAs:
- 對象非常簡單,比如一個字或者一個圖片缩赛,設(shè)置cacheAs=”bitmap”不但不提高性能耙箍,反而會損失性能。
- 容器內(nèi)有經(jīng)常變化的內(nèi)容酥馍,比如容器內(nèi)有一個動畫或者倒計時辩昆,如果再對這個容器設(shè)置cacheAs=”bitmap”,會損失性能物喷÷辈模可以通過查看Canvas統(tǒng)計信息的第一個值,判斷是否一直在刷新Canvas緩存峦失。
/**
* 指定顯示對象是否緩存為靜態(tài)圖像扇丛。功能同cacheAs的normal模式。建議優(yōu)先使用cacheAs代替尉辑。
*/
public function get cacheAsBitmap():Boolean {
return cacheAs !== "none";
}
public function set cacheAsBitmap(value:Boolean):void {
//TODO:去掉關(guān)聯(lián)
cacheAs = value ? (_$P["hasFilter"] ? "none" : "normal") : "none";
}
注意設(shè)置cacheAsBitmap=true帆精,實質(zhì)上等同于cacheAs的normal模式,并不是bitmap模式隧魄。當值為”normal”時卓练,Canvas下進行畫布緩存,webgl模式下進行命令緩存购啄。webGL下命令緩存模式只會減少節(jié)點遍歷及命令組織襟企,不會減少drawcall,性能中等狮含。
4.文字描邊
在運行時顽悼,設(shè)置了描邊的文本比沒有描邊的文本多調(diào)用一次繪圖指令。此時几迄,文本對CPU的使用量和文本的數(shù)量成正比蔚龙。因此,盡量使用替代方案來完成同樣的需求映胁。
對于幾乎不變動的文本內(nèi)容木羹,可以使用cacheAs降低性能消耗。
對于內(nèi)容經(jīng)常變動解孙,但是使用的字符數(shù)量較少的文本域坑填,可以選擇使用位圖字體。
5.Text.changeText會直接修改繪圖指令中該文本繪制的最后一條指令弛姜,這種前面的繪圖指令依舊存在的行為會導致changeText只使用于以下情況:
文本始終只有一行穷遂。
文本的樣式始終不變(顏色、粗細娱据、斜體、對齊等等)。
四中剩、CPU優(yōu)化
參考減少CPU使用量
1.減少動態(tài)屬性查找
JavaScript中任何對象都是動態(tài)的忌穿,你可以任意地添加屬性。然而结啼,在大量的屬性里查找某屬性可能很耗時掠剑。如果需要頻繁使用某個屬性值,可以使用局部變量來保存它:
private function foo():void
{
var prop = target.prop;
// 使用prop
process1(prop);
process2(prop);
process3(prop);
}
另外郊愧,項目中盡量減少try catch的使用朴译,被try catch的函數(shù)執(zhí)行會變得非常慢
2.計時器里盡可能不要在循環(huán)里創(chuàng)建對象及復雜計算
?LayaAir提供兩種計時器循環(huán)來執(zhí)行代碼塊。
Laya.timer.frameLoop執(zhí)行頻率依賴于幀頻率属铁,可通過Stat.FPS查看當前幀頻眠寿。
Laya.timer.loop執(zhí)行頻率依賴于參數(shù)指定時間。
Laya.timer.frameLoop(1, this, animateFrameRateBased);
Laya.stage.on("click", this, dispose);
private function dispose():void
{
Laya.timer.clear(this, animateFrameRateBased);
}
?當一個對象的生命周期結(jié)束時焦蘑,記得清除其內(nèi)部的Timer
3.盡量少用autoSize與getBounds
public function getBounds():Rectangle
獲取本對象在父容器坐標系的矩形顯示區(qū)域盯拱。計算量較大,盡量少用例嘱,如果需要頻繁使用狡逢,可以通過手動設(shè)置setBounds來緩存自身邊界信息,從而避免比較消耗性能的計算
var sp:Sprite = new Sprite();
sp.autoSize = true;
sp.graphics.drawRect(0, 0, 100, 100, "#FF0000");
Laya.stage.addChild(sp);
autoSize在獲取寬高并且顯示列表的狀態(tài)發(fā)生改變時會重新計算(autoSize通過getBoudns計算寬高)拼卵。所以對擁有大量子對象的容器應(yīng)用autoSize是不可取的奢浑。如果設(shè)置了size,autoSize將不起效腋腮。
Laya.loader.load("res/apes/monkey2.png", Handler.create(this, function()
{
var texture:Texture = Laya.loader.getRes("res/apes/monkey2.png");
var sp:Spirte = new Sprite();
sp.graphics.drawTexture(texture, 0, 0);
sp.size(texture.width, texture.height);
Laya.stage.addChild(sp);
}));
使用Graphics.drawTexture并不會自動設(shè)置容器的寬高雀彼,但是可以使用Texture的寬高賦予容器。毋庸置疑低葫,這是最高效的方式详羡。
4.根據(jù)活動狀態(tài)改變幀頻
幀頻有三種模式,
Stage.FRAME_SLOW維持FPS在30嘿悬;
Stage.FRAME_FAST維持FPS在60实柠;
Stage.FRAME_MOUSE則選擇性維持FPS在30或60幀。
?有時并不需要讓游戲以60FPS的速率執(zhí)行善涨,因為30FPS已經(jīng)能夠滿足多數(shù)情況下人類視覺的響應(yīng)窒盐,但是鼠標交互時,30FPS可能會造成畫面的不連貫钢拧,于是Stage.FRAME_MOUSE應(yīng)運而生蟹漓。
5.使用callLater
callLater使代碼塊延遲至本幀渲染前執(zhí)行。如果當前的操作頻繁改變某對象的狀態(tài)源内,此時可以考慮使用callLater葡粒,以減少重復計算。
考慮一個圖形,對它設(shè)置任何改變外觀的屬性都將導致圖形重繪:
var rotation:int = 0,
scale:int = 1,
position:int = 0;
private function setRotation(value):void
{
this.rotation = value;
update();
}
private function setScale(value):void
{
this.scale = value;
update();
}
private function setPosition(value):void
{
this.position = value;
update();
}
public function update()
{
console.log('rotation: ' + this.rotation +
'\tscale: ' + this.scale + '\tposition: ' + position);
}
setRotation(90);
setScale(2);
setPosition(30);
控制臺的打印結(jié)果是:
rotation: 90scale: 1position: 0
rotation: 90scale: 2position: 0
rotation: 90scale: 2position: 30
update被調(diào)用了三次嗽交,并且最后的結(jié)果是正確的卿嘲,但是前面兩次調(diào)用都是不需要的。
?嘗試將三處update改為:
Laya.timer.callLater(this, update);
?此時夫壁,update只會調(diào)用一次拾枣,并且是我們想要的結(jié)果。
6.圖片/圖集加載
在完成圖片/圖集的加載之后盒让,引擎就會開始處理圖片資源梅肤。如果加載的是一張圖集,會處理每張子圖片邑茄。如果一次性處理大量的圖片姨蝴,這個過程可能會造成長時間的卡頓。
在游戲的資源加載中撩扒,可以將資源按照關(guān)卡似扔、場景等分類加載。在同一時間處理的圖片越好搓谆,當時的游戲響應(yīng)速度也會更快炒辉。在資源使用完成后,也可以予以卸載泉手,釋放內(nèi)存黔寇。
7.每幀只計算一部分
我先介紹一下我們的戰(zhàn)斗,在野外的戰(zhàn)斗斩萌,是由客戶端計算殺死這波怪的過程缝裤,再由服務(wù)端驗證這個殺怪過程的合法性,再給出殺怪的收益颊郎。計算的過程是這樣的憋飞,主角遇到一個怪,向他走過去姆吭,走到可距離怪小于釋放技能的攻擊范圍時榛做,釋放技能,然后要用敵我雙方所有與戰(zhàn)斗相關(guān)的屬性内狸,計算出是否命中检眯,是否爆擊,是否觸發(fā)各種效果昆淡,每個效果會不會加某些屬性之類锰瘸。最后得到怪物最終傷害,最終雙方屬性有什么變化等昂灵。這一系列的計算避凝,雖然是純數(shù)學的計算舞萄,但因為數(shù)量的內(nèi)容很多,所以也是一個比較耗性能的操作恕曲。這只是有一只怪的情況鹏氧。一般我們的怪是都不是一只一只出來的,而我們的主角的技能也大部分不是單體攻擊技能佩谣。所以技能會同時攻擊兩個目標,這時实蓬,這兩個目標就會分別計算傷害茸俭。這還只是兩只怪,我們游戲里一般一出來就是很多只怪安皱,在某些玩法里出現(xiàn)幾十甚至近百只怪调鬓。真的,免羊大戰(zhàn)這個玩法就是看誰的場景里先有100只怪誰就輸酌伊。那計算量就很大了腾窝。那我們是否可以只計算一次傷害,另一只怪就用前一只怪計算的傷害來減少CPU的運算量呢居砖?不行虹脯,第一,是否命中奏候,是獨立運行的循集,我們不能做成命中就所有的怪都命中中,不命中就所有的怪都不命中蔗草,這樣表現(xiàn)會很糟糕咒彤。第二,怪和怪不一定是相同的怪咒精。第三镶柱,攻擊的結(jié)果不只是造成傷害,還有加BUFF模叙,會給敵我雙方屬性做出變化歇拆。那我的屬性變化了,對第二只怪有可能計算出來的值就不一樣向楼。
那我怎么做呢查吊。我是把每只要被攻擊的目標,放到一個待計算列表里湖蜕,每一幀逻卖,只拿出若干個進行計算,這樣有的怪會晚幾幀才會飄出傷害昭抒,在視覺上是沒有區(qū)別的评也。但就不會在釋放技能的時候卡一下炼杖。
8.Laya.Stage.getTimeFromFrameStart
/**
* <p>獲得距當前幀開始后,過了多少時間盗迟,單位為毫秒坤邪。</p>
* <p>可以用來判斷函數(shù)內(nèi)時間消耗,通過合理控制每幀函數(shù)處理消耗時長
罚缕,避免一幀做事情太多艇纺,對復雜計算分幀處理,能有效降低幀率波動邮弹。</p>
*/
public function getTimeFromFrameStart():Number {
return Browser.now() - _frameStartTime;
}
數(shù)據(jù)層的數(shù)據(jù)被修改后黔衡,會拋出通知。關(guān)注該數(shù)據(jù)的正在顯示的界面就會收到該通知腌乡,然后去取到數(shù)據(jù)刷新界面的顯示盟劫。這個刷新界面的顯示內(nèi)容就不可預估了,有可能是一個復雜界面与纽,要刷新也許還會刪除一些顯示對象侣签,添加一些顯示對象。性能消耗就可大可小急迂。
如果這時服務(wù)服同時推過來若干條數(shù)據(jù)要處理影所,那性能消耗就完全不能預計了。在這里要做的優(yōu)化是袋毙,什么情況下服務(wù)端會在短時間內(nèi)推大量的數(shù)據(jù)過來型檀,如果有可能,就要對協(xié)議的方式做修改听盖,以減少推送的次數(shù)的大小胀溺。如果不能做修改,那就要把服務(wù)器推過來的數(shù)據(jù)放到一個隊列里皆看,每幀只處理一部分仓坞。Laya里是有一個方法,在Stage下的腰吟,可以取得當時時間距離當前幀開始的時間已經(jīng)經(jīng)過了多少毫秒无埃,我們可以利用這個方法判斷處理協(xié)議,直到這幀快要達到這幀預期的時間毛雇,就余下的協(xié)議放到下一幀去處理嫉称。
這樣會不會讓協(xié)議處理被慢呢?不會灵疮,因為原來在同一幀里去處理的話织阅,需要的時間也是大于一幀,也是要卡在那里等協(xié)議處理完震捣,也是等了這么久荔棉。放到下一幀闹炉,也是過了這么久才處理完。不同的是润樱,原來是卡著游戲渣触,其他一切都動不了拉在等處理完,現(xiàn)在是不卡著讓用戶感覺不到在等的處理完壹若。所以效果會更好些嗅钻。
但這里要注意,就算其他邏輯太多引起本幀沒有剩余時間去處理一條協(xié)議了舌稀,也至少要處理一到兩條協(xié)議啊犬,不然在比較差的設(shè)備上,也許會因為機器卡壁查,就永遠都沒法處理協(xié)議,表現(xiàn)上就會和沒收到服務(wù)端數(shù)據(jù)一樣了剔应。
9.View.createView
比如界面里有個水平滾動的功能睡腿,里邊每一頁都是道具的列表,每個道具列表里又有若干層峻贮。在第一次打開這個界面的時候席怪,我們的程序就會創(chuàng)建這個界面的對象,就需要創(chuàng)建很多顯示對象纤控,這時會卡住很久挂捻。玩過我們游戲的人就會發(fā)現(xiàn),這個界面打的時候船万,會先顯示底上邊的按鈕刻撒,然后顯示第一頁的部分道具格子的底,然后再是另一部分道具格子的底耿导,然后是顯示一部分道具圖標声怔,再是另一部分道具圖標。我說這么長舱呻,然后也就是在不到一秒的時間內(nèi)醋火,只是大家可以感覺得到一部分一部分的顯示。就不顯得卡箱吕。我是改寫了View里的createView方法芥驳,會每幀只初始化若干個顯示對象。