【架構拾集】簡易的 Android 混合應用框架的外掛架構設計
在上一篇文章《ofollow,noindex" target="_blank">【架構拾集】WebView 的 JavaScript Bridge 設計 》裡,我們介紹了 Android、iOS JavaScript Bridge 的一些 相關設計。
這篇文章,則針對上一篇文章,做一些相應的外掛管理機制相關的補充。該方案基於 Cordova 框架的外掛管理方案,做了儘可能的精簡。
技術遠景
作為專案的開發人員,我們希望擁有一個模組化的方案,及對手的外掛管理機制,它在解耦應用程式碼的同時,可以提供更好的外掛化管理方案。
架構設計
參考了 Cordova 的設計——通過類名(即外掛名)來建立對應的例項(newInstance),對應的外掛機制載入主要的程式碼如下所示:
private CordovaPlugin instantiatePlugin(String className) { CordovaPlugin ret = null; try { Class<?> c = null; if ((className != null) && !("".equals(className))) { c = Class.forName(className); } if (c != null & CordovaPlugin.class.isAssignableFrom(c)) { ret = (CordovaPlugin) c.newInstance(); } } catch (Exception e) { e.printStackTrace(); System.out.println("Error adding plugin " + className + "."); } return ret; }
對應的,我們只需要建立自己的CordovaPlugin
類即可,使用時呼叫對應的execute
方法:
import java.util.Map; public interface BridgePlugin { void execute(Map parameters, BridgePlugin bridgePluginCallback); }
在完成執行結束後,則呼叫相應的回撥方法即可:
import com.alibaba.fastjson.JSONObject; public interface PluginCallback { void sendPluginResult(JSONObject message); }
即對應於如下的程式碼:
locationPlugin.execute(pluginParams, message -> { buildData(message, callbackId); offer("success"); });
接著我們面臨的挑戰是,如何下載這些外掛?於是,便編寫了一個簡單的 gradle 指令碼來測試:
ext.addPlugins = { plugins -> delete "${buildDir}/bridge-plugins/" def hasCorePlugins = false def sidePlugins = [] def corePlugins = [] def pluginsSource = "https://github.com/phodal" def CORE_STRING = "core." for (plugin in plugins) { if(!plugin.startsWith(CORE_STRING)) { sidePlugins.push(plugin) } else { hasCorePlugins = true corePlugins.push(plugin) } } if (hasCorePlugins) { def git = Git.cloneRepository() .setURI(pluginsSource + "/core-plugins") .setDirectory(new File("${buildDir}/bridge-plugins/core")) .call() for (corePlugin in corePlugins) { def pluginName = corePlugin.substring(CORE_STRING.size(), corePlugin.size()) println "handle plugin:" + pluginName copy { from "${buildDir}/bridge-plugins/core/" + pluginName into "${projectDir}/app/src/main/java/com/phodal/plugins/core/" + pluginName } } } if (sidePlugins.size > 0) { for (sidePlugin in sidePlugins) { println "handle plugin:" + sidePlugin def git = Git.cloneRepository() .setURI(pluginsSource + "/" + sidePlugin) .setDirectory(new File("${buildDir}/bridge-plugins/side/" + sidePlugin)) .call() copy { from "${buildDir}/bridge-plugins/side/" + sidePlugin into "${projectDir}/app/src/main/java/com/phodal/plugins/side/" + sidePlugin } } } }
對應的外掛下載邏輯是:
core.