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

調(diào)試性能的Adobe AIR應(yīng)用程序

移動(dòng)開(kāi)發(fā)
應(yīng)用程序性能是長(zhǎng)期的。這是與生俱來(lái)的。為了確保一個(gè)應(yīng)用程序性能良好,每個(gè)部分都必須性能良好。某個(gè)部分出現(xiàn)失誤就會(huì)拖累整個(gè)應(yīng)用程序。編寫一個(gè)大型應(yīng)用程序時(shí)作者偶爾也會(huì)放松警惕。

性能相關(guān)問(wèn)題往往表明作者無(wú)法理解問(wèn)題鏈中最薄弱的環(huán)節(jié)。以下是我最喜歡提到的一些有關(guān)性能和 AIR 應(yīng)用程序的糟糕提問(wèn):

  • 我的 AIR 應(yīng)用程序會(huì)運(yùn)行如飛嗎?
  • AIR 是否可以達(dá)到執(zhí)行 X 的速度?
  • AIR 執(zhí)行 Y 是否太慢?

(以下內(nèi)容還證明了一點(diǎn),無(wú)論幼稚園老師教了您什么,總會(huì)出現(xiàn)糟糕提問(wèn)這類事物。)

AIR 幾乎總可以通過(guò)應(yīng)用程序?qū)崿F(xiàn)良好性能。而另一方面,AIR 無(wú)法為您這樣做。正如我所說(shuō)的,這是問(wèn)題的本性。

幸運(yùn)的是,標(biāo)準(zhǔn)調(diào)試技術(shù)像適用于編寫桌面軟件一樣適用于 AIR。

合適的提問(wèn)

實(shí)現(xiàn)良好性能的***步,就如同大多數(shù)設(shè)計(jì)問(wèn)題,在于理解您嘗試解決的問(wèn)題。以下是一些針對(duì)您的應(yīng)用程序的合適的提問(wèn):

  • 我的應(yīng)用程序中哪些操作對(duì)于性能比較敏感?
  • 我可以使用什么衡量標(biāo)準(zhǔn)來(lái)測(cè)量這一敏感度?
  • 如何優(yōu)化應(yīng)用程序以達(dá)到這一衡量標(biāo)準(zhǔn)?

大多數(shù)應(yīng)用程序包含大量可以穩(wěn)定運(yùn)行的代碼。不要在這方面浪費(fèi)時(shí)間,尤其是當(dāng)益處低于用戶可以察覺(jué)的閾值時(shí)。務(wù)必將注意力集中在重要方面。

值得優(yōu)化的常見(jiàn)操作示例包括:

  • 圖像、聲音和視頻處理
  • 渲染大型數(shù)據(jù)集或 3D 模型
  • 搜索
  • 響應(yīng)用戶輸入

定義衡量標(biāo)準(zhǔn)

人們往往將性能和速度劃上等號(hào),但千萬(wàn)不要誤以為這是唯一重要的衡量標(biāo)準(zhǔn)。您可能發(fā)現(xiàn)需要針對(duì)內(nèi)存使用或電池壽命進(jìn)行調(diào)試。將這些降至***的應(yīng)用程序也可以被認(rèn)為比那些不降低的應(yīng)用程序性能更高。有時(shí)優(yōu)化其他衡量標(biāo)準(zhǔn)也可以提高速度,但其他時(shí)候需要做出折衷。

無(wú)論測(cè)量什么,您必須測(cè)量一些對(duì)象。如果不測(cè)量任何對(duì)象,您就無(wú)法得知更改是有利于還是有害于性能。良好的衡量標(biāo)準(zhǔn)有以下三個(gè)特性:

  • 它們可以量化??梢詼y(cè)量它們并記錄為數(shù)字。
  • 它們是一致的。您可以反復(fù)測(cè)量它們,并有效地比較測(cè)量結(jié)果。
  • 它們有意義。測(cè)量值中的變化對(duì)應(yīng)于您正在優(yōu)化的對(duì)象。

為了使它更形象,假設(shè)您正在編寫一個(gè)應(yīng)用程序,它將對(duì)一個(gè)大型圖像集執(zhí)行一些圖像處理任務(wù)。在處理過(guò)程中,應(yīng)用程序需要向用戶顯示進(jìn)度反饋。它還必須允許用戶能取消操作,而不是等待操作完成。這是一個(gè)十分簡(jiǎn)單的應(yīng)用程序,但即便如此,它至少仍有三個(gè)重要的衡量標(biāo)準(zhǔn)可供審視。

示例:吞吐量

***個(gè)、最顯而易見(jiàn)的衡量標(biāo)準(zhǔn)是吞吐量。它在這個(gè)示例中是有意義的,因?yàn)槲覀冎雷约罕仨毺幚泶罅繄D像。吞吐量越高,處理完成得越快。

吞吐量可以輕松量化為每單位時(shí)間的處理量。盡管可以測(cè)量已處理圖像的數(shù)量,但當(dāng)圖像大小不一時(shí),測(cè)量字節(jié)數(shù)可以產(chǎn)生一致性更高的值。在這個(gè)示例中,直接測(cè)量每毫秒字節(jié)數(shù)作為吞吐量。

示例:內(nèi)存使用

對(duì)于這個(gè)應(yīng)用程序,一個(gè)不太顯眼的衡量標(biāo)準(zhǔn)是內(nèi)存使用。對(duì)于最終用戶,內(nèi)存使用不像吞吐量那樣顯而易見(jiàn)。為了監(jiān)視內(nèi)存使用,用戶必須運(yùn)行另一個(gè)應(yīng)用程序,如 Activity Monitor。但內(nèi)存使用可能成為一個(gè)限制因素:內(nèi)存不足,此時(shí)應(yīng)用程序?qū)o(wú)法正常運(yùn)行。

內(nèi)存使用對(duì)于我們的圖像處理示例是重要的,因?yàn)檫@些圖像本身很大。我們希望能處理大型圖像-即便是那些超出可用 RAM 的圖像-前提是不出現(xiàn)內(nèi)存不足的情況。內(nèi)存使用按字節(jié)測(cè)量很簡(jiǎn)單。

示例:響應(yīng)時(shí)間

我們的范例應(yīng)用程序的***一個(gè)衡量標(biāo)準(zhǔn)往往被忽略:用戶輸入的響應(yīng)時(shí)間。這個(gè)衡量標(biāo)準(zhǔn)對(duì)于您的所有用戶而言都是顯而易見(jiàn)的,雖然他們很少停下來(lái)測(cè)量它。它也十分普遍。用戶希望所有操作都能得到快速響應(yīng)-無(wú)論是調(diào)整窗口大小、取消某個(gè)操作還是鍵入文本。

用戶認(rèn)為某些衡量標(biāo)準(zhǔn)是線性的,而響應(yīng)時(shí)間卻有一個(gè)重要的閾值。輸入響應(yīng)只要超過(guò) 100 毫秒左右,用戶就會(huì)有慢的感覺(jué)。如果您的應(yīng)用程序響應(yīng)速度始終低于這個(gè)閾值,就沒(méi)有進(jìn)一步優(yōu)化的必要了。顯然,這個(gè)衡量標(biāo)準(zhǔn)可以按毫秒輕松量化。

響應(yīng)時(shí)間對(duì)于圖像處理應(yīng)用程序是一個(gè)重要挑戰(zhàn),因?yàn)樘幚砣魏我粡垐D像的時(shí)間都遠(yuǎn)遠(yuǎn)超出 100 毫秒。在某些編程環(huán)境中,通過(guò)在連續(xù)計(jì)算線程以外的線程上處理用戶輸入來(lái)解決這個(gè)問(wèn)題。而在內(nèi)部,這種解決方法需要操作系統(tǒng)快速切換線程環(huán)境,確保用戶輸入線程可以及時(shí)響應(yīng)。但 AIR 不提供明確的線程模型,所以必須直接完成這一切換操作。下一部分將說(shuō)明這一操作。以下范例說(shuō)明了設(shè)置圖像處理的三種不同方式,它們針對(duì)不同的衡量標(biāo)準(zhǔn)而優(yōu)化:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.             <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" frameRate='45'> 
  3.   <mx:Script> 
  4.   <![CDATA[ 
  5.             private static const DATASET_SIZE_MB:int = 100; 
  6.    
  7.             private function doThroughput():void { 
  8.             var start:Number = new Date().time; 
  9.             var data:ByteArray = new ByteArray(); 
  10.             data.length = DATASET_SIZE_MB * 1024 * 1024; 
  11.             filter( data ); 
  12.             var end:Number = new Date().time; 
  13.             _throughputLabel.text = ( data.length / ( end - start )) + " bytes/msec"; 
  14.             } 
  15.    
  16.             private function doMemory():void { 
  17.             var start:Number = new Date().time; 
  18.             var data:ByteArray = new ByteArray(); 
  19.             data.length = 1024 * 1024; 
  20.             for( var chunk:int = 0; chunk < DATASET_SIZE_MB; chunk++ ) { 
  21.             filter( data ); 
  22.             } 
  23.             var end:Number = new Date().time; 
  24.             _memoryLabel.text = ( DATASET_SIZE_MB * data.length / ( end - start )) + " bytes/msec"; 
  25.             } 
  26.    
  27.             private function doResponse():void { 
  28.             _chunkStart = new Date().time; 
  29.             _chunkData = new ByteArray(); 
  30.             _chunkData.length = 100 * 1024; 
  31.             _chunksRemaining = DATASET_SIZE_MB * 1024 / 100;  
  32.             _chunkTimer = new Timer( 1, 1 ); 
  33.             _chunkTimer.addEventListener( TimerEvent.TIMER_COMPLETE, doChunk ); 
  34.             _chunkTimer.start(); 
  35.             } 
  36.    
  37.             private function doChunk( event:TimerEvent ):void { 
  38.             var iterStart:Number = new Date().time; 
  39.             while( _chunksRemaining > 0 ) { 
  40.             filter( _chunkData ); 
  41.             _chunksRemaining--; 
  42.  
  43.             var now:Number = new Date().time; 
  44.             if( now - iterStart > 90 ) break; 
  45.             } 
  46.    
  47.             if( _chunksRemaining > 0 ) { 
  48.             _chunkTimer.start(); 
  49.             } else { 
  50.             var end:Number = new Date().time; 
  51.             _responseLabel.text = ( DATASET_SIZE_MB * 1024 * 1024 / ( end - _chunkStart )) + " bytes/msec";  
  52.             } 
  53.             } 
  54.    
  55.             private var _chunkStart:Number; 
  56.             private var _chunkData:ByteArray; 
  57.             private var _chunksRemaining:int; 
  58.             private var _chunkTimer:Timer; 
  59.    
  60.             private function filter( data:ByteArray ):void { 
  61.             for( var i:int = 0; i < data.length; i++ ) { 
  62.             data[i] = data[i] * data[i] + 2; 
  63.             } 
  64.             } 
  65.             private function onMouseMove( event:MouseEvent ):void { 
  66.             var global:Point = new Point( event.stageX, event.stageY ); 
  67.             var local:Point = _canvas.globalToLocal( global ); 
  68.             _button.x = local.x; 
  69.             _button.y = local.y; 
  70.             } 
  71.    
  72.             ]]> 
  73.   </mx:Script> 
  74.    
  75.   <mx:HBox width='100%' height='100%'> 
  76.   <mx:VBox width='50%' height='100%'> 
  77.   <mx:Button label='Measure throughput' click='doThroughput();' /> 
  78.   <mx:Label  id='_throughputLabel' /> 
  79.   <mx:Button label='Reduce memory use' click='doMemory();' /> 
  80.   <mx:Label  id='_memoryLabel' /> 
  81.   <mx:Button label='Maintain responsiveness' click='doResponse();' /> 
  82.   <mx:Label  id='_responseLabel' /> 
  83.   </mx:VBox> 
  84.   <mx:Canvas  
  85.             width='50%' height='100%' 
  86.             id="_canvas"  
  87.             horizontalScrollPolicy="off" 
  88.             verticalScrollPolicy="off" 
  89.             backgroundColor="white" 
  90.             mouseMove='onMouseMove( event );' 
  91.   > 
  92.   <mx:Label text="Move Me" id="_button" /> 
  93.   </mx:Canvas> 
  94.   </mx:HBox> 
  95.   </mx:WindowedApplication> 

進(jìn)行測(cè)量

當(dāng)確定并定義衡量標(biāo)準(zhǔn)后,您首先必須能測(cè)量它們,隨后才能處理它們。只有通過(guò)前后兩次的測(cè)量和跟蹤,您才能確定那些變化的影響。盡可能同時(shí)跟蹤所有衡量標(biāo)準(zhǔn),這樣可以了解為優(yōu)化一個(gè)衡量標(biāo)準(zhǔn)所做的更改對(duì)其他衡量標(biāo)準(zhǔn)產(chǎn)生的影響。

測(cè)量吞吐量

可以通過(guò)程序輕松測(cè)量吞吐量。測(cè)量吞吐量的基本模式為:

  1. start_msec = new Date().time 
  2. do_work() 
  3. end_msec = new Date().time 
  4. rate = bytes_processed / ( end_msec - start_msec )  

測(cè)量?jī)?nèi)存

內(nèi)存更復(fù)雜一些。包括 AIR 在內(nèi)的大多數(shù)運(yùn)行時(shí)環(huán)境不提供可以確定應(yīng)用程序內(nèi)存使用的適當(dāng) API。***使用外部工具監(jiān)視內(nèi)存使用,如 Activity Monitor (Mac OS X)、任務(wù)管理器 (Windows)、BigTop (Mac OS X) 等。選擇一個(gè)監(jiān)視工具后,您需要決定要跟蹤哪個(gè)內(nèi)存衡量標(biāo)準(zhǔn)。

虛擬內(nèi)存是跟蹤工具的頭號(hào)報(bào)告對(duì)象。 人如其名,它不會(huì)測(cè)量進(jìn)程使用的物理 RAM 量。可以將它想象為進(jìn)程使用的內(nèi)存地址空間量。在某個(gè)時(shí)刻,分配給進(jìn)程的一部分內(nèi)存通常會(huì)存儲(chǔ)在磁盤而不是 RAM 中。人們通常認(rèn)為 RAM 量以及占用的磁盤空間之和就是進(jìn)程的虛擬內(nèi)存,但地址空間的某些部分可能不在這兩個(gè)地方。具體情況取決于操作系統(tǒng)以及它根據(jù)不同目的分配虛擬內(nèi)存部分的方式。

根據(jù)虛擬內(nèi)存包含的內(nèi)容,應(yīng)用程序虛擬內(nèi)存的絕對(duì)大小可能不是一個(gè)重要的衡量標(biāo)準(zhǔn)。您的應(yīng)用程序相對(duì)于其他類似應(yīng)用程序的虛擬內(nèi)存可能是重要的,但依然很難進(jìn)行有效比較。虛擬內(nèi)存最重要的一個(gè)方面是它隨著時(shí)間流逝產(chǎn)生的行為:無(wú)限增長(zhǎng)表明存在內(nèi)存泄漏。其他內(nèi)存衡量標(biāo)準(zhǔn)中可能不顯示內(nèi)存泄漏,因?yàn)槿绻匆眯孤┑膬?nèi)存,它們會(huì)調(diào)入磁盤并駐留在那里。

可供監(jiān)視的***內(nèi)存衡量標(biāo)準(zhǔn)是專用字節(jié),它測(cè)量進(jìn)程單獨(dú)使用的 RAM 量。這個(gè)衡量標(biāo)準(zhǔn)直接表明您的應(yīng)用程序?qū)φ麄€(gè)系統(tǒng)產(chǎn)生的影響,它使用的是共享資源。

專用字節(jié)會(huì)隨著應(yīng)用程序分配和取消分配內(nèi)存而波動(dòng)。它也會(huì)隨著應(yīng)用程序活動(dòng)或空閑而波動(dòng),空閑時(shí)部分頁(yè)面會(huì)調(diào)入磁盤。要跟蹤專用字節(jié),我建議在您優(yōu)化的操作過(guò)程中使用監(jiān)視工具進(jìn)行定期采樣,即每秒一次。

監(jiān)視工具包含的其他內(nèi)存衡量標(biāo)準(zhǔn)包括駐留大小和共享字節(jié)。駐留大小是您的進(jìn)程所使用的 RAM 總量,它由專用字節(jié)和共享字節(jié)組成。共享字節(jié)是與其他進(jìn)程共享的 RAM 部分。這些部分通常包含只讀資源,如共享庫(kù)或系統(tǒng)框架中的代碼。雖然您可以跟蹤這些衡量指標(biāo),應(yīng)用程序目前對(duì)專用字節(jié)值的控制度***,問(wèn)題也最多。

響應(yīng)時(shí)間

響應(yīng)時(shí)間***用秒表測(cè)量。當(dāng)用戶執(zhí)行操作時(shí)開(kāi)始計(jì)時(shí),如單擊按鈕時(shí)。當(dāng)應(yīng)用程序響應(yīng)時(shí)停止計(jì)時(shí),通常更改顯示的用戶界面即可。將兩個(gè)計(jì)時(shí)相減就可以得出測(cè)量值。

優(yōu)化流程

有了目標(biāo)和衡量標(biāo)準(zhǔn),就可以進(jìn)行優(yōu)化了。流程本身很簡(jiǎn)單,并且應(yīng)當(dāng)很常見(jiàn)。重復(fù)以下三個(gè)步驟,直至完成:

  1. 測(cè)量
  2. 分析
  3. 修改

大致而言,分析可能產(chǎn)生兩種更改中的一種:設(shè)計(jì)或代碼。

設(shè)計(jì)更改

設(shè)計(jì)更改通常影響***。但是,在游戲后期進(jìn)行設(shè)計(jì)更改難度可能更大,所以定義并測(cè)量性能目標(biāo)之前不要耽擱太久。

例如,我們回到圖像處理應(yīng)用程序。一種單純的實(shí)施方法是:將每個(gè)圖像完整加載到內(nèi)存中,處理它,然后將結(jié)果寫回磁盤。這個(gè)應(yīng)用程序的內(nèi)存使用峰值(專用字節(jié))主要就是已加載圖像大小的函數(shù)。如果圖像超出可用 RAM,應(yīng)用程序?qū)⑹ ?/p>

圖像處理操作很少是全局的;大多數(shù)操作每次可以在圖像的某個(gè)部分上執(zhí)行。通過(guò)將圖像分為固定大小的多個(gè)塊并且逐個(gè)處理這些塊,您可以將應(yīng)用程序的內(nèi)存使用峰值限制為選定的數(shù)值。這樣,處理超出可用 RAM 的圖像也成為可能。

修改設(shè)計(jì)后,請(qǐng)務(wù)必重新評(píng)估所有衡量標(biāo)準(zhǔn)。它們之間始終會(huì)出現(xiàn)一些相互作用,因?yàn)樵O(shè)計(jì)發(fā)生了變化。那些更改有時(shí)可能會(huì)出乎想象。當(dāng)我構(gòu)建這個(gè)范例應(yīng)用程序的原型時(shí),按固定大小的塊處理圖像并未大幅改變應(yīng)用程序的吞吐量,我預(yù)計(jì)它可能變慢。

代碼更改

當(dāng)不再需要增強(qiáng)設(shè)計(jì)時(shí),可轉(zhuǎn)向代碼調(diào)試。這個(gè)方面可以嘗試許多技術(shù)。其中有些是 ActionScript 特有的;有些則不然。

切記不要過(guò)早應(yīng)用代碼更改。它們可能會(huì)犧牲可讀性和性能結(jié)構(gòu)。雖然不一定每次都會(huì)很糟,但是如果過(guò)早應(yīng)用代碼更改,它們會(huì)降低您改進(jìn)和維護(hù)應(yīng)用程序的能力。正如 Donald Knuth 所說(shuō),“過(guò)早的優(yōu)化是一切罪惡的源頭。”

特制的測(cè)試應(yīng)用程序

真實(shí)的應(yīng)用程序往往較大、較復(fù)雜并且滿是快速運(yùn)行的代碼。為了幫助您既愛(ài)那個(gè)優(yōu)化精力集中在主要操作上,可考慮創(chuàng)建一個(gè)專用測(cè)試應(yīng)用程序。

除了其他優(yōu)勢(shì),測(cè)試應(yīng)用程序提供了一個(gè)包含測(cè)試的空間(即,用于測(cè)量吞吐量),您無(wú)需將這個(gè)代碼包含在最終的應(yīng)用程序中。

當(dāng)然,將您的改進(jìn)移回應(yīng)用程序時(shí),您需要驗(yàn)證優(yōu)化結(jié)果是否依然有效。

分塊

如前所述,AIR 運(yùn)行時(shí)不提供在后臺(tái)線程上執(zhí)行應(yīng)用程序代碼的機(jī)制。在計(jì)算密集型任務(wù)過(guò)程中嘗試保持響應(yīng)度時(shí),這個(gè)問(wèn)題尤為棘手。

與空間分塊可用于優(yōu)化內(nèi)存使用一樣,時(shí)間分塊可以將計(jì)算分為多個(gè)短時(shí)運(yùn)行部分。通過(guò)響應(yīng)各部分之間的用戶輸入,您可以保持應(yīng)用程序的響應(yīng)度。

以下偽代碼每次可以執(zhí)行約 90 毫秒的工作,然后把控制權(quán)交給主事件循環(huán)。主事件循環(huán)確保已處理鼠標(biāo)單擊等操作。根據(jù)這一時(shí)間安排,可以在 100 毫秒內(nèi)處理大多數(shù)用戶輸入,從用戶角度而言,應(yīng)用程序的響應(yīng)速度已足夠。

  1. var timer:Timer = new Timer( 1, 1 ) 
  2.   timer.addEventListener( TimerEvent.TIMER, doChunk )  
  3.   function doChunk( event:Event ):void { 
  4.     var start:Number = new Date().time 
  5.     while( workRemaining ) { 
  6.       doWork() 
  7.         var now:Number = new Date().time 
  8.         if( now - start > 90 ) { 
  9.           // reschedule more work to occur after input 
  10.         if( workRemaining )  
  11.            timer.start() 
  12.         break 
  13.       }  
  14.     } 
  15.   }  

在此例中,為了保持響應(yīng)度,doWork() 的運(yùn)行時(shí)間必須遠(yuǎn)遠(yuǎn)小于塊持續(xù)時(shí)間。為了保持在 100 毫秒的最糟情況下,運(yùn)行時(shí)間不能超出 10 毫秒。

再次強(qiáng)調(diào),采用這類方法后,請(qǐng)重新測(cè)量所有衡量標(biāo)準(zhǔn)。在我的圖像處理應(yīng)用程序中,采用這種分塊方法后吞吐量下降了約 10%。另一方面,我的應(yīng)用程序在所有用戶輸入的 100 毫秒內(nèi)可以做出響應(yīng),而不僅僅是在圖像之間。我認(rèn)為這是一個(gè)合理的折衷。

包裝

創(chuàng)建高性能的應(yīng)用程序并非易事,但要回應(yīng)嚴(yán)格的測(cè)量、分析和不斷改進(jìn)會(huì)遇到問(wèn)題。AIR 應(yīng)用程序在這個(gè)問(wèn)題上沒(méi)有很大區(qū)別。

性能同時(shí)也是一個(gè)不斷變化的目標(biāo)。不僅每一組改進(jìn)可能影響到其他衡量標(biāo)準(zhǔn),底層硬件、操作系統(tǒng)和其他更改也會(huì)改變快與慢之間的平衡。即便是您在優(yōu)化的對(duì)象也可能隨時(shí)間發(fā)生變化。

憑借充分的實(shí)戰(zhàn)經(jīng)驗(yàn),您可以創(chuàng)建出高性能的 AIR 應(yīng)用程序并使它們持之以恒。切記不要放松警惕。只要有一個(gè)功能變慢,用戶就會(huì)發(fā)問(wèn),“您的應(yīng)用程序是否可以達(dá)到執(zhí)行 X 的速度?”

 

關(guān)于作者

自 Adobe AIR 誕生并發(fā)展出新穎的安裝技術(shù)以來(lái),Oliver 一直致力于這個(gè)領(lǐng)域。在轉(zhuǎn)向 AIR 之前,他致力于 Adobe LiveCycle,而在加入 Adobe 之前,他從事的領(lǐng)域很廣,包括金融服務(wù)、數(shù)字信號(hào)處理和視頻游戲。他有時(shí)為 Dr. Dobb's Journal 撰稿,并且是 Kidos Computer 技術(shù)咨詢委員會(huì)的成員。他獲得了斯坦福大學(xué)的計(jì)算機(jī)本科及碩士學(xué)位。

 

 

責(zé)任編輯:佚名 來(lái)源: Adobe
相關(guān)推薦

2011-11-17 15:01:37

AdobeAIR移動(dòng)應(yīng)用

2011-11-17 15:31:12

AdobeAIR

2012-02-15 13:26:56

IndexedDB

2013-05-14 10:33:57

AIR Android應(yīng)用程序描述文件

2022-12-25 18:03:13

Debug原理軟件

2010-08-04 10:13:40

FlexBuilder

2012-02-28 13:52:45

Adobe AIRAndroidFlash

2012-03-09 10:46:35

Adobe AIR是什Adobe AIRAIR

2012-03-09 13:26:53

2012-03-09 13:52:28

Adob??e AIRiOS

2011-08-08 13:35:50

Web應(yīng)用WANWeb應(yīng)用程序

2011-11-16 16:21:09

AdobeAIR

2011-11-16 15:47:04

AdobeAIRiOS應(yīng)用

2011-05-05 18:08:43

云計(jì)算Windows AzuPaaS

2010-02-04 09:41:03

Android應(yīng)用程序

2010-11-25 10:05:22

Visual StudSilverlightWCF

2014-06-18 16:45:26

Adobe

2010-03-26 13:12:27

2023-03-30 08:29:14

HTTP緩存Web應(yīng)用

2011-04-11 14:45:41

性能設(shè)計(jì)官方文檔Android
點(diǎn)贊
收藏

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