Cordova源码深入分析-第三讲

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010479969/article/details/79537882

上一讲讲解了js端,调用到java端的代码逻辑

这一讲,主要介绍,js->native带有callback的形式,是如何调用回去的

上一篇介绍到了调用照相机代码的地方,在最后调用了:sendPluginResult

这里调用一下:

    @Override
    public void sendPluginResult(PluginResult cr, String callbackId) {
        nativeToJsMessageQueue.addPluginResult(cr, callbackId);
    }

NativeToJsMessageQueue.java

    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);//将消息放到队列中,里面含有
    }
    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) { //如果没有pause则直接执行,有pause的话,下次触发执行
                activeBridgeMode.onNativeToJsMessageAvailable(this);//开始执行
            }
        }
    }

根据不同的bridge走不同代码,这里先列举一种情况

      @Override
        public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
            cordova.getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    String js = queue.popAndEncodeAsJs();//取出刚才加入进去的消息,并且转换为js
                    if (js != null) {
                        engine.loadUrl("javascript:" + js, false);
                    }
                }
            });
        }

这里是组装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();
        
            Log.v("XPC","ret="+ret);//ret=cordova.callbackFromNative('Camera1024838304',false,9,["No Image Selected"],false);
            return ret;
        }
    }

看一下encodeAsJsMessage

        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(",[");
                buildJsMessage(sb);
                sb.append("],")
                        .append(pluginResult.getKeepCallback())
                        .append(");");
            }
        }

这样就调回了js端的cordova.js端

    callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
        try {
            var callback = cordova.callbacks[callbackId];//根据callbackId找到我们之前的函数,这个在上一讲中,写到过,
            if (callback) {
                if (isSuccess && status == cordova.callbackStatus.OK) {
                    callback.success && callback.success.apply(null, args);//这里会直接调用camera.js的成功和失败方法中
                } else if (!isSuccess) {
                    callback.fail && callback.fail.apply(null, args);
                }
                /*
                else
                    Note, this case is intentionally not caught.
                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
                    which is used to remove a callback from the list without calling the callbacks
                    typically keepCallback is false in this case
                */
                // Clear callback if not expecting any more results
                if (!keepCallback) {
                    delete cordova.callbacks[callbackId];
                }
            }
        }
        catch (err) {
            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
            console && console.log && console.log(msg);
            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
            throw err;
        }
    },
本讲结束!!!!下一讲java端的插件系统是如何建立关联的










猜你喜欢

转载自blog.csdn.net/u010479969/article/details/79537882