如何在 Android 上執行 ClojureScript

oschina發表於2015-10-11

在過去的幾天裡,我有了開發生涯中最有意義的經歷之一, 想在這裡跟大家分享。

現在我們已經讓 ClojureScript 可以在 Android 上執行了。不是在一個 WebView 裡面,也不是利用像 Cordova 這樣的東西,而是實實在在的執行在一個嵌入式的 JavaScript 引擎中。到底發生了什麼?

在 Android 上執行 ClojureScript

最近,我們做了一些工作建立出了一個 iOS 的 ClojureScript REPL 應用,Replete。整個看上去很酷,而對應的 Android 應用就只算勉強能建立出來。不幸的是,我的 Android 技術平平,也不能立馬就上手。

不過,這方面 Tahmid Sadik 的技術還能上得了檯面。

Tahmid 可以把UI都串起來,也能將 Rhino 例項化並對JavaScript語句進行計算,但是接下來讓引導式的 ClojureScript 執行起來對他而言可謂是一次挑戰。

不過在此之前,他必須在他的 app 裡將 ClojureScript 引導起來。引導這個詞被我特意標明,指出他需要用 Google 的 Closure 依賴管理系統把 ClojureScript 執行時啟動起來,沒有 JavaScript,也沒有其他的優化(例如 :none 模式),根據需要,可以定義 CLOSURE_IMPORT_SCRIPT 環境變數。如果想包含一個 REPL,用這種方式來引入執行時是很重要的。這也為在你的 REPL 包含原始碼級的名字空間提供了支援。

實際上,Replete 也需要做這些,用到的是 Ambly 的一個功能。我當然知道,Replete 是一個獨立的 REPL,並不需要 Ambly。不過我使用了一個小花招,可以複用這個功能,讓 ClojureScript 啟動在 Replete 裡執行。

順便說一下,我最初是打算用 React Native 來實現 Replete 的。結果發現,使用 React Native 的 ClojureScript 支援還為時尚早,而可以引導的 ClojureScript 確實只是初期的功能,要想能夠實際工作還需要做很多努力。所以,對於 Replete,我還是保持簡單吧,就算是 Goby 也沒有用到。

對於上述的結果,好的一點是不需要 React Native 的依賴(Android 版還沒有正式公開發布),也沒有 Goby 的依賴(只支援 iOS)。Replete 內建的 ClojureScript 非常簡潔,使用傳統的 iOS 的 UI,事實證明這對 Tahmid 去完成同樣功能的 Android 版很有幫助。

讓我們回到故事的開始:本質上 Tahmid 複製了 Ambly 的 Bootstrap 邏輯,按照順序逐一的執行了在 Rhino 裡的 JavaScript 語句。不過時不時的他會遇到一些奇怪的問題,我的記憶中幾個月前也會遇到類似的問題,在研究過 Ambly 的程式碼後,我給了一點建議。

之後,他基本上可以引導成功 ClosureScriptle。

cljs.core.apply.call(null,cljs.core.inc,new cljs.core.PersistentVector(null, 1, 5, cljs.core.PersistentVector.EMPTY_NODE, [1], null))

這行就是(apply inc [1])需要繫結的JavaScript程式碼

然後Tahmid終於有了2.0。真棒!這應該是有史以來的第一次,在基於Android的嵌入式的Rhino上跑起來ClojureScript。

接下來,需要嘗試用起來reader, analyzer, 和compiler。現在我們來試一下,只需要簡單的使用Replete裡的JavaScript,讓Android的app執行Replete的read_eval_print函式,引數為字串 (+ 1 2),如果工作正常,那麼恭喜,ClojureScript已經成功啟動了。

replete.core.read_eval_print.call(null,'(+ 1 2)')

且慢,Transit 裡執行 goog.require(‘replete.core’);的時候出了問題,應該是跟 randomUUID 有關。悲劇了,看上去顯然還有很多地方需要處理。

不過沒關係,Replete 之前一直嘗試用不同的方式載入 analysis 快取,感謝 Karl Mikkelsen,我們有了一個可用的版本只使用純 JavaScript,沒有任何依賴。把這個用起來之後,在把print回撥弄好(這樣類似 println 這樣的方法就可以工作了),接下來 Tahmid 就通過Slack通知我:

I got 3
(+ 1 2) = 3

… 然後不斷煩我,還會擅自發部落格。就這樣,引導的 ClojureScript REPL 在 Android 上誕生了!

Tahmid 在介面上封裝了一些東西,修復了 JavaScript/ClojureScript 整合的一些小問題之後就釋出了Replicator

簡直就是一場暴風雨!

現在,Tahmid 正在用 JavaScriptCore 替換 Rhino,這就沒那麼快了。

我認為這將使速度提升。這為我們在 Android 上使用 JavaScriptCore 進行本地交換的功能提供一些重要的基礎。

從大圖片來看,我真的認為 ClojureScript 在 Android 上執行很快。特別是使用 JavaScriptCore。對於這個觀點的問題,可以看看 Bocko 對 Android 的 Vladimir Iakovlev 的埠在啟動速度上的差異。

以上是在模擬器上執行的結果,但是,我仍然認為它顯示了 ClojureScript 真正的實現了在移動裝置上減少計算延時的承諾。我認為是時候讓 ClojureScript 活躍起來,用於為移動裝置開發應用!

相關文章