深刻Weex系列(四)之Module組件源碼解析

一、前言

通過前面兩篇文章的實踐,咱們學習了Weex的使用。本篇開始咱們深刻Weex的源碼,一塊兒探索Weex在安卓平臺上是如何構建一套JS的運行框架,那從Module開始提及吧。html

本文從源碼入手分析Module的註冊、調用、回調等流程,而且分析一個Weex自帶Module的實現。android

二、初識Module

2.1 Module的定位

《Android 擴展》中咱們能夠看到Module的定位:git

Module 擴展非UI的特定功能,例如 sendHttp、openURL 等。github

也就是說是非UI類型的功能提供,在本地註冊供Js運行時調用,有了Module,咱們就能夠本身擴展一些Weex沒有提供的能力給Js,讓Js更增強大!apache

2.2 Module的使用

還記不記得在上兩篇文章中咱們就用到了Module來實現網絡請求的能力,聲明+調用即完成了網絡請求的調用;bash

var stream = weex.requireModule('stream') // 聲明
    stream.fetch // 請求複製代碼

三、Module源碼分析

3.1 Module註冊

Module註冊時序圖
Module註冊時序圖

對於註冊,也分爲本地註冊和Js註冊微信

  • 本地註冊:
    • 若是這個Module是全局的,則直接反射建立Module對象,而後存儲在sGlobalModuleMap中;
    • Native註冊Module的過程很簡單,在sModuleFactoryMap中保存了Module的Name及對應的ModuleFactory;
  • Js註冊:
    • WXBridge是Native與Js交互的橋樑,執行的是JNI層的Java_com_taobao_weex_bridge_WXBridge_execJS方法;
    • Js的註冊最終調用到了WXBridge的execJS方法,類型爲METHOD_REGISTER_MODULES;

備註:註冊的意義在於Js與Native定義了一個協議,一個對應關係;調用的時候能找到Module。weex

3.2 Module調用

Module調用時序圖
Module調用時序圖

調用分析:網絡

  • Module的調用是由Native開始,經過WXBridge這個Js與Native交互的橋樑;
  • 在WXModuleManager會調用findModule,上面本地註冊的時候有提到(是全局的話則直接反射建立),此處未被建立的Module對象會被建立;
  • 調用getMethodInvoker方法獲取調用方法包裝成的對象Invoker;
  • 經過NativeInvokerHelper來調用,實際是是MethodInvoker反射調用的;

3.3 Native回調Js

Native回調Js時序圖
Native回調Js時序圖

調用分析:框架

  • NativeInvokerHelper反射調用方法的時候回將JSCallback包裝成SimpleJSCallback對象;
  • Native調用完成須要回調的時候調用到WXBridgeManager的callbackJavascript方法;
  • 隨後發送消息,任務執行就被切換到了WeexJSBridgeThread線程;
  • 最後也是調用的WXBridge回調Js端;

3.4 Module源碼總結

Module的源碼並不複雜:

  • 在客戶端定義了Module來實現特定能力例如網絡請求(就是一個提供方法的類);
  • 而後註冊到Native和Js(註冊過程就是讓雙方能找到對方);
  • 調用是從Js發起,經過WXBridge(交互橋樑,之後還會常常遇到)與Native交互的;
  • Native找到本地註冊的Class,經過反射調用Module方法;
  • 回調也是經過WXBridge,傳遞信息給Js;

3.5 Module相關的關鍵類

Module相關的關鍵類
Module相關的關鍵類

四、特定Module實現分析

分析了Module的註冊、調用、回調等步驟,咱們就來實例分析一個Weex中自帶的Module:WXStreamModule,咱們網絡請求的功能就是它實現的,在Weex代碼中咱們調用網絡請求的是fetch方法,那麼咱們在WXStreamModule方法中尋找fetch方法:

@JSMethod(uiThread = false)
  public void fetch(String optionsStr, final JSCallback callback, JSCallback progressCallback){
            ......

            String method = optionsObj.getString("method");
            String url = optionsObj.getString("url");
            JSONObject headers = optionsObj.getJSONObject("headers");
            String body = optionsObj.getString("body");
            String type = optionsObj.getString("type");
            int timeout = optionsObj.getIntValue("timeout");

            sendRequest()

            ......
  }複製代碼
  • 經過上述optionsObj中獲取各類數據的方式,咱們能夠推知在Weex代碼中怎麼去聲明想要的參數,例如:Weex的Demo中沒有寫傳遞header的例子,咱們查看獲取Header的方式也知道須要將其封裝成一個JsonObject,從根源來發現解決問題的途徑是看源碼的好處之一,源碼面前了無祕密!

  • sendRequest是經過IWXHttpAdapter實現的,沒有設置的話會使用DefaultWXHttpAdapter;而後在一個FixedThreadPool裏經過HttpURLConnection執行的網絡請求。

public class DefaultWXHttpAdapter implements IWXHttpAdapter {
    private ExecutorService mExecutorService = Executors.newFixedThreadPool(3);

    @Override
    public void sendRequest(final WXRequest request, final OnHttpListener listener) {
        HttpURLConnection connection = openConnection(request, listener);
    }

}複製代碼

備註:經過細看WXStreamModule的源碼咱們不難發現最終網絡請求的默認執行類DefaultWXHttpAdapter有必定缺陷,固定線程數的線程池實際上並不適合網絡請求的場景,尤爲在網絡請求密集的場景下(整個模塊、甚至應用都使用Weex來作,這種場景不會罕見)。所以若是咱們要大面積使用Weex最好本身實現IWXHttpAdapter或者調用Native的方法。這是看源碼的另外一好處:從源碼角度分析框架實現的利弊,定製更適合本身業務的實現。

自定義Module比較簡單,就不在本文細說了,能夠參照官方文檔或者自帶的Module的實現,也能夠參考我寫的WeexList,裏面有自定義Module的使用。

五、Module總結

  • Module的定位是擴展非UI的特定功能;
  • Module源碼的分析,包括:註冊、調用、回調等;
  • 分析一個自帶的Module:WXStreamModule;
  • 經過本文也能夠發現源碼閱讀的好處:
    • 從根源來發現解決問題的途徑(Header的傳遞方式);
    • 源碼角度分析框架實現的利弊,定製適合本身的實現(DefaultWXHttpAdapter裏的問題,本身定製);

歡迎持續關注Weex源碼分析項目:Weex-Analysis-Project

歡迎關注微信公衆號:按期分享Java、Android乾貨!

歡迎關注
歡迎關注
相關文章
相關標籤/搜索