之前寫了一篇flex和js之間的通信,還記得最開(kāi)始研究這兩門語(yǔ)言如何交互,一晃我的任務(wù)也快做完了,公司的realspace產(chǎn)品之開(kāi)了js的API,但是現(xiàn)在使用flex產(chǎn)品的人也比較多,要求開(kāi)設(shè)flex的三維API,已經(jīng)過(guò)去幾個(gè)月了,產(chǎn)品也上線了,有興趣的可以在https://github.com/SuperMap/Flex-Realspace下載,這是一個(gè)利用as與js交互放在了一個(gè)完整的產(chǎn)品里。
網(wǎng)上也有很多關(guān)于flex和js通信的文章,不過(guò)不知道大家有沒(méi)有注意到好像都需要把js文件放在固定的文件下(flex調(diào)用js),并且需要在index.template.html文件里面動(dòng)手腳,而且你把源代碼考給團(tuán)隊(duì)的其他人,發(fā)現(xiàn)flash builder導(dǎo)進(jìn)去后重新生成了index.template.html,又得自己修改一下,不是很麻煩嗎?如果你是需要此技術(shù)做自己的產(chǎn)品的話我建議你一定要看一下我想出的辦法,也許會(huì)幫了不少人哦!
一個(gè)大項(xiàng)目或者產(chǎn)品,在js代碼里面估計(jì)都會(huì)有很多用原型建的類,在flex端估計(jì)也有很多功能。我們的假設(shè)場(chǎng)景是你正在使用flex制作項(xiàng)目,不過(guò)有一些功能只能通過(guò)js來(lái)實(shí)現(xiàn),所以你將部分功能使用js封裝成了一些js的文件,希望通過(guò)as與js之間的通信來(lái)使用as語(yǔ)言調(diào)用js里面的功能。js文件基本已經(jīng)寫好了,但是因?yàn)樾枰诓簧俚胤蕉帜_團(tuán)隊(duì)協(xié)作起來(lái)不方便,我這篇文章就是用來(lái)解決這個(gè)問(wèn)題的。
一、設(shè)計(jì)好代碼
首先我們需要明白的是:js文件在啟動(dòng)之后被加載到html頁(yè)面里面,我們可以通過(guò)ExternalInterface.call("js的方法",參數(shù));在flex端調(diào)用js端的方法,我們可以通過(guò)ExternalInterface.addCallback("對(duì)外公開(kāi)的方法名",具體實(shí)現(xiàn)的方法);來(lái)解決在js端調(diào)用flex端的方法。
現(xiàn)在我們需要思考:js里面有很多功能,我們每次調(diào)用js功能都得去調(diào)用相關(guān)的方法嗎?那樣as和js之間的耦合不是太高了,不符合設(shè)計(jì)模式,并且很麻煩。同樣js這邊需要回調(diào)(常用在事件回調(diào)上)flex的方法時(shí),方法很多,我們是不是也要在flex端動(dòng)態(tài)注冊(cè)那么多個(gè)方法名稱呢?那樣不怕名稱沖突嗎?所以這樣的實(shí)現(xiàn)都是不可取的。
為了達(dá)到低耦合,我將as和js之間的通信設(shè)定為只有兩座橋,as調(diào)用js功能永遠(yuǎn)只會(huì)通過(guò)調(diào)用js里面的固定方法,js回調(diào)flex的功能也只能調(diào)用在程序初始化flex端動(dòng)態(tài)創(chuàng)建的唯一的一個(gè)方法。這樣as和js之間的通信永遠(yuǎn)只通過(guò)這兩個(gè)方法來(lái)交互,就不會(huì)出現(xiàn)之前的很多問(wèn)題。但是大家肯定想問(wèn)如何知道我這一次調(diào)用的功能和我下一次調(diào)用的有什么區(qū)別怎么辦?那就是在參數(shù)上面做手腳了。說(shuō)白了就是通過(guò)參數(shù)來(lái)判斷你的行為。
在我們flex realspace產(chǎn)品面as調(diào)用js的功能都是通過(guò)var result:Object=ExternalInterface.call("SuperMap.Web.Util.ApplicationManager.initBridgeFlexToJs",object);這一局來(lái)的,SuperMap.Web.Util.ApplicationManager.initBridgeFlexToJs是在js端的一個(gè)文件里面的方法,唯一的as訪問(wèn)js的通道,特殊的是object,這是一個(gè)鍵值對(duì),形如:
復(fù)制代碼 代碼如下:
var realArgument:Array=[strServerUrl.toString()+"$String"];
var array:Object={
action:"FUNCTION",
key:this.KEY,
functionName:"checkPluginUpdate",
isReturn:true,
realArgument:realArgument
};
其實(shí)這些有點(diǎn)類似json,用來(lái)傳遞數(shù)據(jù)的,而我自定義的一個(gè)格式是用來(lái)傳遞行為操作的,這個(gè)你們可以自己定義,反正核心就是通過(guò)參數(shù)來(lái)判斷你的行為,方法永遠(yuǎn)調(diào)用同一個(gè),這點(diǎn)明白了就是自己設(shè)計(jì)上的事情,不過(guò)在解析的時(shí)候有點(diǎn)麻煩哈!
二、打包js代碼
如果你的代碼符合我這樣的邏輯,交互通過(guò)兩座橋來(lái)通信,那么我們就開(kāi)始下一步,其實(shí)這樣設(shè)計(jì)后已經(jīng)可以使得自己的產(chǎn)品交互起來(lái)很方便了,我當(dāng)時(shí)花了一個(gè)月就是這么做的,都做的差不多了,上面交代說(shuō)js代碼不能開(kāi)放出來(lái),而且每次都需要修改index.template.html文件,太麻煩,希望flex端的開(kāi)放人員完全看不到j(luò)s的任何東西,要求需要把js文件打包成為swc文件,通過(guò)去調(diào)用swc文件里面的js來(lái)實(shí)現(xiàn)功能,我當(dāng)時(shí)一聽(tīng)這簡(jiǎn)直就是不可能的嘛!不過(guò)后來(lái)研究了好久,發(fā)現(xiàn)這樣可以實(shí)現(xiàn),并且還有它的優(yōu)勢(shì)。
首先我們需要知道如何把js文件打包成為swc文件,新建一個(gè)庫(kù)項(xiàng)目,將你的js文件都放進(jìn)去,如下圖:
我建的項(xiàng)目叫bridge,里面有我所有的js文件,還有不少as文件,細(xì)心的發(fā)現(xiàn)每一個(gè)js文件旁邊都有一個(gè)...Stream.as文件,這里就是重點(diǎn)了,我們?nèi)绾尾拍馨裫s文件打包到swc里面呢,flex提供了一種流的方式,例如上面的ApplicationManager.js文件,我們創(chuàng)建一個(gè)類ApplicationManagerStream繼承于flash.utils.ByteArray,代碼如下:
復(fù)制代碼 代碼如下:
package SuperMap.Js
{
import flash.utils.ByteArray;
/**
* 制定js文件以及打包方式
*/
[Embed(source="ApplicationManager.js", mimeType="application/octet-stream")]
public class ApplicationManagerStream extends ByteArray
{
public function ApplicationManagerStream()
{
super();
}
}
}
里面會(huì)自動(dòng)生成好打包好的swc文件
現(xiàn)在問(wèn)題又來(lái)了,里面是二進(jìn)制的東西,我們?nèi)绾问褂冒。皇俏覀兤綍r(shí)寫的as類,寫了什么方法引用這個(gè)包直接使用就行。
所以我們還需要一個(gè)as類。這里我創(chuàng)建IncludeStream.as,代碼如下:
復(fù)制代碼 代碼如下:
(編輯:武林網(wǎng))
新聞熱點(diǎn)
疑難解答