NativeToJsMessageQueue的作用

该类用来向js发送插件的执行结果,同时维护native到js的桥接方式,代码太多不叙述全部,参见NativeToJsMessageQueue.java文件。

//..此处有代码省略...


  /**
   * 插件执行结果最终都封装为JsMessage对象并丢在该数组中
   */
  private final LinkedList<JsMessage> queue = new LinkedList<JsMessage>();

  /**
   * native支持的桥接模式数组,可以在SystemWebViewEngine.java中找到它的初始化
   */
  private ArrayList<BridgeMode> bridgeModes = new ArrayList<BridgeMode>();
  /**
   * 当前native到js的桥接模式
   */
  private BridgeMode activeBridgeMode;


//..此处有代码省略..

/**
 * 将队列中数据吐出给js,返回js执行脚本字符串,
 */
 public String popAndEncodeAsJs() {
        synchronized (this) {
            int length = queue.size();
            if (length == 0) {
                return null;
            }
            int totalPayloadLen = 0;
            int numMessagesToSend = 0;
            for (JsMessage message : queue) {
                int messageSize = message.calculateEncodedLength() + 50; // overestimate.
                if (numMessagesToSend > 0 && totalPayloadLen + messageSize > MAX_PAYLOAD_SIZE && MAX_PAYLOAD_SIZE > 0) {
                    break;
                }
                totalPayloadLen += messageSize;
                numMessagesToSend += 1;
            }
            boolean willSendAllMessages = numMessagesToSend == queue.size();
            StringBuilder sb = new StringBuilder(totalPayloadLen + (willSendAllMessages ? 0 : 100));
            // Wrap each statement in a try/finally so that if one throws it does
            // not affect the next.
            for (int i = 0; i < numMessagesToSend; ++i) {
                JsMessage message = queue.removeFirst();
                if (willSendAllMessages && (i + 1 == numMessagesToSend)) {
                    message.encodeAsJsMessage(sb);
                } else {
                    sb.append("try{");
                    message.encodeAsJsMessage(sb);
                    sb.append("}finally{");
                }
            }
            if (!willSendAllMessages) {
                sb.append("window.setTimeout(function(){cordova.require('cordova/plugin/android/polling').pollOnce();},0);");
            }
            for (int i = willSendAllMessages ? 1 : 0; i < numMessagesToSend; ++i) {
                sb.append('}');
            }
            String ret = sb.toString();
            return ret;
        }
    }

    /**
     * Add a JavaScript statement to the list.
     */
    public void addJavaScript(String statement) {
        enqueueMessage(new JsMessage(statement));
    }

    /**
     *  将插件的执行结果封装为JsMessage对象
     */
    public void addPluginResult(PluginResult result, String callbackId) {
        if (callbackId == null) {
            LOG.e(LOG_TAG, "Got plugin result with no callbackId", new Throwable());
            return;
        }
        // Don't send anything if there is no result and there is no need to
        // clear the callbacks.
        boolean noResult = result.getStatus() == PluginResult.Status.NO_RESULT.ordinal();
        boolean keepCallback = result.getKeepCallback();
        if (noResult && keepCallback) {
            return;
        }
        JsMessage message = new JsMessage(result, callbackId);
        if (FORCE_ENCODE_USING_EVAL) {
            StringBuilder sb = new StringBuilder(message.calculateEncodedLength() + 50);
            message.encodeAsJsMessage(sb);
            message = new JsMessage(sb.toString());
        }

        enqueueMessage(message);
    }

  //使用当前已经激活的桥接方式向js回传数据
    private void enqueueMessage(JsMessage message) {
        synchronized (this) {
            if (activeBridgeMode == null) {
                LOG.d(LOG_TAG, "Dropping Native->JS message due to disabled bridge");
                return;
            }
            queue.add(message);
            if (!paused) {
                activeBridgeMode.onNativeToJsMessageAvailable(this);
            }
        }
    }

//..此处有代码省略..

      /*
       *eval桥接模式,通过webview.evaluateJavascript 来向前端回传数据
      */
    public static class EvalBridgeMode extends BridgeMode {
        private final CordovaWebViewEngine engine;
        private final CordovaInterface cordova;

        public EvalBridgeMode(CordovaWebViewEngine engine, CordovaInterface cordova) {
            this.engine = engine;
            this.cordova = cordova;
        }

        @Override
        public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
            cordova.getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    String js = queue.popAndEncodeAsJs();//将插件的执行结果拼成js字符串并交由webveiw执行
                    if (js != null) {
                        engine.evaluateJavascript(js, null);
                    }
                }
            });
        }
    }

//..此处有代码省略..



// 拼接js字符串 cordova.callbackFromNative()调用js定义好的方法并加入插件的结果做为参数
 void encodeAsJsMessage(StringBuilder sb) {
            if (pluginResult == null) {
                sb.append(jsPayloadOrCallbackId);
            } else {
                int status = pluginResult.getStatus();
                boolean success = (status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal());
                sb.append("cordova.callbackFromNative('")
                  .append(jsPayloadOrCallbackId)
                  .append("',")
                  .append(success)
                  .append(",")
                  .append(status)
                  .append(",[");
                switch (pluginResult.getMessageType()) {
                    case PluginResult.MESSAGE_TYPE_BINARYSTRING:
                        sb.append("atob('")
                          .append(pluginResult.getMessage())
                          .append("')");
                        break;
                    case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
                        sb.append("cordova.require('cordova/base64').toArrayBuffer('")
                          .append(pluginResult.getMessage())
                          .append("')");
                        break;
                    default:
                    sb.append(pluginResult.getMessage());
                }
                sb.append("],")
                  .append(pluginResult.getKeepCallback())
                  .append(");");
            }
        }
    }

    //..此处有代码省略..

results matching ""

    No results matching ""