diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/DoricDriver.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/DoricDriver.java index 71d58d06..07141df2 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/DoricDriver.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/DoricDriver.java @@ -8,6 +8,7 @@ import com.github.penfeizhou.doric.async.AsyncResult; import com.github.penfeizhou.doric.engine.DoricJSEngine; import com.github.penfeizhou.doric.utils.DoricConstant; import com.github.penfeizhou.doric.utils.DoricLog; +import com.github.penfeizhou.doric.utils.ThreadMode; import com.github.pengfeizhou.jscore.JSDecoder; import java.util.concurrent.Callable; @@ -25,6 +26,7 @@ public class DoricDriver implements IDoricDriver { private final Handler mUIHandler; private final Handler mJSHandler; + @Override public AsyncResult invokeContextEntityMethod(final String contextId, final String method, final Object... args) { final Object[] nArgs = new Object[args.length + 2]; nArgs[0] = contextId; @@ -35,6 +37,7 @@ public class DoricDriver implements IDoricDriver { return invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE, nArgs); } + @Override public AsyncResult invokeDoricMethod(final String method, final Object... args) { return AsyncCall.ensureRunInHandler(mJSHandler, new Callable() { @Override @@ -49,6 +52,20 @@ public class DoricDriver implements IDoricDriver { }); } + @Override + public AsyncResult asyncCall(Callable callable, ThreadMode threadMode) { + switch (threadMode) { + case JS: + return AsyncCall.ensureRunInHandler(mJSHandler, callable); + case UI: + return AsyncCall.ensureRunInHandler(mUIHandler, callable); + case INDEPENDENT: + default: + return AsyncCall.ensureRunIExecutor(mBridgeExecutor, callable); + } + } + + private static class Inner { private static final DoricDriver sInstance = new DoricDriver(); } @@ -60,22 +77,12 @@ public class DoricDriver implements IDoricDriver { mJSHandler = doricJSEngine.getJSHandler(); } - public void runOnJS(Runnable runnable) { - mJSHandler.post(runnable); - } - - public void runOnUI(Runnable runnable) { - mUIHandler.post(runnable); - } - - public void runIndependently(Runnable runnable) { - mBridgeExecutor.execute(runnable); - } public static DoricDriver getInstance() { return Inner.sInstance; } + @Override public AsyncResult createContext(final String contextId, final String script, final String source) { return AsyncCall.ensureRunInHandler(mJSHandler, new Callable() { @Override diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/IDoricDriver.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/IDoricDriver.java index f999ccff..b902ef02 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/IDoricDriver.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/IDoricDriver.java @@ -2,8 +2,11 @@ package com.github.penfeizhou.doric; import com.github.penfeizhou.doric.async.AsyncResult; +import com.github.penfeizhou.doric.utils.ThreadMode; import com.github.pengfeizhou.jscore.JSDecoder; +import java.util.concurrent.Callable; + /** * @Description: com.github.pengfeizhou.doric * @Author: pengfei.zhou @@ -14,11 +17,7 @@ public interface IDoricDriver { AsyncResult invokeDoricMethod(final String method, final Object... args); - void runOnJS(Runnable runnable); - - void runOnUI(Runnable runnable); - - void runIndependently(Runnable runnable); + AsyncResult asyncCall(Callable callable, ThreadMode threadMode); AsyncResult createContext(final String contextId, final String script, final String source); diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncCall.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncCall.java index 1f51adb3..d5f23cab 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncCall.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncCall.java @@ -4,6 +4,7 @@ import android.os.Handler; import android.os.Looper; import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; /** * @Description: com.github.pengfeizhou.doric.async @@ -34,4 +35,19 @@ public class AsyncCall { } return asyncResult; } + + public static AsyncResult ensureRunIExecutor(ExecutorService executorService, final Callable callable) { + final AsyncResult asyncResult = new AsyncResult<>(); + executorService.execute(new Runnable() { + @Override + public void run() { + try { + asyncResult.setResult(callable.call()); + } catch (Exception e) { + asyncResult.setError(e); + } + } + }); + return asyncResult; + } } diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncResult.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncResult.java index 632c4d26..ac5a6af5 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncResult.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/async/AsyncResult.java @@ -27,6 +27,14 @@ public class AsyncResult { } } + public boolean hasResult() { + return result != EMPTY; + } + + public R getResult() { + return (R) result; + } + public void setCallback(Callback callback) { this.callback = callback; if (result instanceof Throwable) { diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricBridgeExtension.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricBridgeExtension.java index 03b50e93..7ae86468 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricBridgeExtension.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricBridgeExtension.java @@ -3,6 +3,8 @@ package com.github.penfeizhou.doric.extension.bridge; import android.text.TextUtils; import com.github.penfeizhou.doric.DoricContext; +import com.github.penfeizhou.doric.async.AsyncCall; +import com.github.penfeizhou.doric.async.AsyncResult; import com.github.penfeizhou.doric.plugin.DoricNativePlugin; import com.github.penfeizhou.doric.plugin.ModalPlugin; import com.github.penfeizhou.doric.DoricContextManager; @@ -14,6 +16,7 @@ import com.github.pengfeizhou.jscore.JavaValue; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; /** * @Description: Doric @@ -34,41 +37,46 @@ public class DoricBridgeExtension { } } - public JavaValue callNative(String contextId, String module, String methodName, String callbackId, JSDecoder jsDecoder) { - DoricContext context = DoricContextManager.getContext(contextId); + public JavaValue callNative(String contextId, String module, String methodName, final String callbackId, final JSDecoder jsDecoder) { + final DoricContext context = DoricContextManager.getContext(contextId); DoricPluginInfo pluginInfo = pluginInfoMap.get(module); if (pluginInfo == null) { DoricLog.e("Cannot find plugin class:%s", module); return new JavaValue(false); } - DoricNativePlugin doricNativePlugin = context.obtainPlugin(pluginInfo); + final DoricNativePlugin doricNativePlugin = context.obtainPlugin(pluginInfo); if (doricNativePlugin == null) { DoricLog.e("Cannot obtain plugin instance:%s,method:%", module); return new JavaValue(false); } - Method method = pluginInfo.getMethod(methodName); + final Method method = pluginInfo.getMethod(methodName); if (method == null) { DoricLog.e("Cannot find plugin method in class:%s,method:%s", module, methodName); return new JavaValue(false); } DoricMethod doricMethod = method.getAnnotation(DoricMethod.class); - try { - Class[] classes = method.getParameterTypes(); - Object ret; - if (classes.length == 0) { - ret = method.invoke(doricNativePlugin); - } else if (classes.length == 1) { - ret = method.invoke(doricNativePlugin, createParam(context, classes[0], callbackId, jsDecoder)); - } else { - ret = method.invoke(doricNativePlugin, - createParam(context, classes[0], callbackId, jsDecoder), - createParam(context, classes[1], callbackId, jsDecoder)); + Callable callable = new Callable() { + @Override + public JavaValue call() throws Exception { + Class[] classes = method.getParameterTypes(); + Object ret; + if (classes.length == 0) { + ret = method.invoke(doricNativePlugin); + } else if (classes.length == 1) { + ret = method.invoke(doricNativePlugin, createParam(context, classes[0], callbackId, jsDecoder)); + } else { + ret = method.invoke(doricNativePlugin, + createParam(context, classes[0], callbackId, jsDecoder), + createParam(context, classes[1], callbackId, jsDecoder)); + } + return DoricUtils.toJavaValue(ret); } - return DoricUtils.toJavaValue(ret); - } catch (Exception e) { - DoricLog.e("callNative error:%s", e.getLocalizedMessage()); - return new JavaValue(false); + }; + AsyncResult asyncResult = context.getDriver().asyncCall(callable, doricMethod.thread()); + if (asyncResult.hasResult()) { + return asyncResult.getResult(); } + return new JavaValue(true); } private Object createParam(DoricContext context, Class clz, String callbackId, JSDecoder jsDecoder) { diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricMethod.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricMethod.java index baeef317..6f246e6d 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricMethod.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/extension/bridge/DoricMethod.java @@ -1,5 +1,7 @@ package com.github.penfeizhou.doric.extension.bridge; +import com.github.penfeizhou.doric.utils.ThreadMode; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -17,11 +19,5 @@ import java.lang.annotation.Target; public @interface DoricMethod { String name() default ""; - Mode thread() default Mode.INDEPENDENT; - - enum Mode { - UI, - JS, - INDEPENDENT, - } + ThreadMode thread() default ThreadMode.INDEPENDENT; } diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/plugin/ModalPlugin.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/plugin/ModalPlugin.java index 16976d29..7da68c09 100644 --- a/Android/doric/src/main/java/com/github/penfeizhou/doric/plugin/ModalPlugin.java +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/plugin/ModalPlugin.java @@ -6,6 +6,7 @@ import com.github.penfeizhou.doric.DoricContext; import com.github.penfeizhou.doric.extension.bridge.DoricComponent; import com.github.penfeizhou.doric.extension.bridge.DoricMethod; import com.github.penfeizhou.doric.extension.bridge.DoricPromise; +import com.github.penfeizhou.doric.utils.ThreadMode; import com.github.pengfeizhou.jscore.ArchiveException; import com.github.pengfeizhou.jscore.JSDecoder; @@ -21,7 +22,7 @@ public class ModalPlugin extends DoricNativePlugin { super(doricContext); } - @DoricMethod(name = "toast", thread = DoricMethod.Mode.UI) + @DoricMethod(name = "toast", thread = ThreadMode.UI) public void toast(JSDecoder decoder, DoricPromise promise) { try { Toast.makeText(getDoricContext().getContext(), decoder.string(), Toast.LENGTH_SHORT).show(); diff --git a/Android/doric/src/main/java/com/github/penfeizhou/doric/utils/ThreadMode.java b/Android/doric/src/main/java/com/github/penfeizhou/doric/utils/ThreadMode.java new file mode 100644 index 00000000..33a26531 --- /dev/null +++ b/Android/doric/src/main/java/com/github/penfeizhou/doric/utils/ThreadMode.java @@ -0,0 +1,12 @@ +package com.github.penfeizhou.doric.utils; + +/** + * @Description: com.github.penfeizhou.doric.utils + * @Author: pengfei.zhou + * @CreateDate: 2019-07-20 + */ +public enum ThreadMode { + UI, + JS, + INDEPENDENT, +}