前幾天面試一個(gè)高級(jí)工程師味抖,他有多年的Android開(kāi)發(fā)經(jīng)驗(yàn)甥啄,同一應(yīng)用也常常負(fù)責(zé)做IOS的版本,后端人力不夠時(shí)也去幫忙改改BUG撼玄,在小公司里人很容易被訓(xùn)練成多面手夺姑。在談到混合開(kāi)發(fā)時(shí),他說(shuō)之前還用過(guò)PhoneGap進(jìn)行過(guò)開(kāi)發(fā)掌猛,那么我很自然地就問(wèn)他:“你對(duì)現(xiàn)在比較流行的React Native怎么看呢盏浙?”
結(jié)果他一臉茫然,不知React Native為何物荔茬。在確認(rèn)不是他聽(tīng)錯(cuò)的情況后废膘,我對(duì)他的看法就改變了,我認(rèn)為對(duì)于目前的移動(dòng)端開(kāi)發(fā)來(lái)說(shuō)慕蔚,沒(méi)用過(guò)React Native并不可恥丐黄,但是沒(méi)聽(tīng)說(shuō)過(guò)的話就很沒(méi)臉混了。
所以孔飒,這一題我們來(lái)談?wù)勗贏ndroid中遇到JavaScript的問(wèn)題灌闺。
面試題:Android中Java和JavaScript如何交互艰争?
先說(shuō)一些基礎(chǔ)的知識(shí),而JavaScript 是一種腳本語(yǔ)言桂对,個(gè)人認(rèn)為他比Java更面像對(duì)象甩卓,它沒(méi)有編譯、鏈接等操作蕉斜,在運(yùn)行時(shí)才動(dòng)態(tài)的進(jìn)行詞法逾柿、語(yǔ)法分析,生成抽象語(yǔ)法樹(shù)和字節(jié)碼蛛勉,然后由解釋器負(fù)責(zé)執(zhí)行或者使用 JIT 將字節(jié)碼轉(zhuǎn)化為機(jī)器碼再執(zhí)行鹿寻。整個(gè)流程由 JavaScript 引擎負(fù)責(zé)完成,在Android手機(jī)上诽凌,這個(gè)JavaScript 引擎就是WebView的實(shí)現(xiàn)內(nèi)核。
在Android 4.4版本中坦敌,原本基于Android WebKit的WebView實(shí)現(xiàn)被換成基于Chromium的WebView實(shí)現(xiàn)侣诵。
在Android應(yīng)用中我們可以通過(guò)WebView從url加載網(wǎng)頁(yè),很多公司在面試時(shí)也會(huì)考查一下面試者是否有Java和JavaScript交互的經(jīng)驗(yàn)狱窘。這里我們也簡(jiǎn)單說(shuō)一下杜顺,Java和JavaScript交互主要分為:
1、Java調(diào)用WebView加載的網(wǎng)頁(yè)上的JavaScript
在Java端可以通過(guò)WebView調(diào)用JavaScript蘸炸,基本格式為:
webView.loadUrl(“javascript:methodName(parameterValues)”)
有時(shí)還要注意這個(gè)javascript:methodName是有參數(shù)還是無(wú)參數(shù)躬络,有返回值的情況也會(huì)有所不同,畢竟我們從webView.loadUrl的接口看不到如何處理返回值搭儒。Android 4.4之后WebView增加了evaluateJavascript接口可以供我們通過(guò)ValueCallback這個(gè)回調(diào)處理返回值穷当。
public void evaluateJavascript(String script, ValueCallback<String> resultCallback)
在4.4之前的版本,常用的思路是Java調(diào)用JavaScript方法淹禾,JavaScript方法執(zhí)行完畢馁菜,再次調(diào)用Java代碼將值返回。
2铃岔、JavaScript調(diào)用本地的Java對(duì)像方法
JavaScript調(diào)用Java需要在WebView通過(guò)addJavascriptInterface添加一個(gè)實(shí)例到WebView的一個(gè)Map對(duì)象中汪疮,也就是下面接口中第一個(gè)參數(shù)。
public void addJavascriptInterface(Object object, String name)
調(diào)用格式為window.?name.methodName(parameterValues)毁习,methodName為object實(shí)例提供的方法智嚷。在Android 4.2之后引入了@JavascriptInterface,被標(biāo)為JavascriptInterface的方法才能在JavaScript端進(jìn)行調(diào)用纺且,也就是說(shuō)在4.2之前的版本開(kāi)放JavaScript調(diào)用Java實(shí)例的功能是有全安隱患的盏道。
因?yàn)镴avaScript端調(diào)用Java時(shí)是通過(guò)反射的方式÷√矗可以在JavaScript端通過(guò)window.?name.getClass().forName反射調(diào)用java.lang.Runtime類的方法(getRuntime)摇天,之后便可以執(zhí)行一些命令做些壞事情了粹湃。
所以在4.2之前的版本一般都建議:
關(guān)閉JavaScript功能(setJavaScriptEnabled);
不使用addJavascriptInterface泉坐;
用removeJavascriptInterface移除系統(tǒng)自帶的實(shí)例(如:WebView默認(rèn)會(huì)addJavascriptInterface添加一個(gè) “searchBoxJavaBridge_” 的實(shí)例)为鳄。
如果非要在4.2之前的版本使用JavaScript功能,那該怎么辦呢腕让?這個(gè)問(wèn)題我也沒(méi)有很好的答案孤钦,你可以試試問(wèn)問(wèn)面試者,看看他們的想法纯丸。
混合開(kāi)發(fā)(Hybrid App)的問(wèn)題
人都是向往懶和舒服的偏形,當(dāng)我們針對(duì)同一業(yè)務(wù)需求要開(kāi)發(fā)多個(gè)版本的移動(dòng)端應(yīng)用時(shí),我們很容易想到能不能像JAVA一樣只寫(xiě)一次代碼在各個(gè)平臺(tái)都可以運(yùn)行觉鼻,所以就產(chǎn)生了一種叫Hybrid App(混合應(yīng)用)開(kāi)發(fā)方式俊扭。
簡(jiǎn)單地說(shuō),原來(lái)一個(gè)項(xiàng)目我們一般要做Web坠陈、Android和IOS三個(gè)應(yīng)用萨惑,現(xiàn)在我們做混合應(yīng)用,用CSS仇矾,HTML和JavaScript編寫(xiě)應(yīng)用庸蔼,在Android和IOS上用Webview做為載體來(lái)運(yùn)行。很多開(kāi)源庫(kù)也為我們寫(xiě)為了JavaScript調(diào)用原生模塊的接口供我們調(diào)用贮匕。只要我們的HTML界面看起來(lái)像手機(jī)自帶的控件姐仅,那么理論上用戶是區(qū)分不開(kāi)是原生的應(yīng)用還是Web應(yīng)用,而且可以動(dòng)態(tài)部署的優(yōu)點(diǎn)也很吸引人刻盐。
但理想是豐滿的掏膏,現(xiàn)實(shí)總是那么殘酷。
性能問(wèn)題首當(dāng)其沖隙疚,IOS的手機(jī)要好些壤追,但在硬件標(biāo)準(zhǔn)參差不齊的Android設(shè)備上,使用Webview加載和渲染JavaScript的性能較差供屉,稍微復(fù)雜一點(diǎn)或CSS動(dòng)畫(huà)多一些行冰,卡頓現(xiàn)象就很常見(jiàn)了。
而且兼容性問(wèn)題也很突出伶丐,包括Android官方的WebView實(shí)現(xiàn)內(nèi)核都發(fā)生了變化悼做,每個(gè)版本所支持的功能也有不同。再加上ROM廠商亂改系統(tǒng)自帶的WebView哗魂,從而導(dǎo)致在各種小細(xì)節(jié)上不同手機(jī)的顯示效果或運(yùn)算結(jié)果不同肛走。
安全問(wèn)題和調(diào)試難的問(wèn)題也不容忽視,最終發(fā)現(xiàn)解決它們成本并不比原生開(kāi)發(fā)的成本低录别。之前Facebook也想使用H5來(lái)做移動(dòng)應(yīng)用朽色,后來(lái)也無(wú)法解決這些問(wèn)題邻吞,最終放棄了,所以才有了今天的React Native葫男。
React Native
正如項(xiàng)目的名字那樣抱冷,React Native的目的是構(gòu)建真正native的應(yīng)用。而不是構(gòu)建在Webview里運(yùn)行的混合模式的應(yīng)用梢褐,開(kāi)發(fā)完全由JavaScript和React來(lái)完成旺遮。簡(jiǎn)單說(shuō)它的原理就是,開(kāi)發(fā)用JavaScript開(kāi)發(fā)Web的方式進(jìn)行開(kāi)發(fā)盈咳,最終在移動(dòng)端會(huì)使用一個(gè)JavascriptCore解釋器引擎來(lái)解析JS相關(guān)文件成相應(yīng)的原生控件再進(jìn)行渲染耿眉,性能上得到了很大的提升。
FaceBook開(kāi)發(fā)React是對(duì)以前思維模式進(jìn)行了改變鱼响,不再追求一次編寫(xiě)到處運(yùn)行鸣剪,而是轉(zhuǎn)而探討:
Learn once,Write anywhere!
小結(jié)
前端的發(fā)展如火如荼热押,而且從業(yè)人數(shù)不可小覷西傀,目前高端的前端開(kāi)發(fā)的薪資待遇方面都很不錯(cuò),也說(shuō)明了市場(chǎng)對(duì)它的認(rèn)可桶癣。雖然目前看,前端開(kāi)發(fā)還有些混亂(開(kāi)發(fā)框架和模式琳瑯滿目)娘锁,難度和復(fù)雜度也在增加牙寞,但并不能排除它一統(tǒng)天下的可能性。
做為Android的工程師莫秆,你無(wú)法確認(rèn)Androd或者IOS會(huì)不會(huì)走Symbian(Nokia用的平臺(tái))的老路间雀,這樣看來(lái),接觸一些前端開(kāi)發(fā)知識(shí)镊屎,對(duì)我們來(lái)說(shuō)是很有必要的惹挟。這也是為什么我會(huì)因?yàn)橐粋€(gè)高級(jí)工程師不知道React Native而改變對(duì)他的看法。