diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricContext.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricContext.java index 128e01d9..54beea8f 100644 --- a/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricContext.java +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricContext.java @@ -1,8 +1,9 @@ package com.github.pengfeizhou.doric; +import com.github.pengfeizhou.doric.async.AsyncResult; import com.github.pengfeizhou.doric.bridge.DoricNativePlugin; import com.github.pengfeizhou.doric.extension.DoricPluginInfo; -import com.github.pengfeizhou.doric.utils.DoricSettableFuture; +import com.github.pengfeizhou.doric.async.SettableFuture; import com.github.pengfeizhou.jscore.JSDecoder; import java.util.HashMap; @@ -25,7 +26,7 @@ public class DoricContext { return DoricDriver.getInstance().createContext(script, alias); } - public DoricSettableFuture callEntity(String methodName, Object... args) { + public AsyncResult callEntity(String methodName, Object... args) { return DoricDriver.getInstance().invokeContextMethod(mContextId, methodName, args); } diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricDriver.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricDriver.java index 1de2f2d2..a314137b 100644 --- a/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricDriver.java +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/DoricDriver.java @@ -1,7 +1,7 @@ package com.github.pengfeizhou.doric; +import com.github.pengfeizhou.doric.async.AsyncResult; import com.github.pengfeizhou.doric.engine.DoricJSEngine; -import com.github.pengfeizhou.doric.utils.DoricSettableFuture; import com.github.pengfeizhou.jscore.JSDecoder; import java.util.Map; @@ -18,7 +18,7 @@ public class DoricDriver { private final AtomicInteger counter = new AtomicInteger(); private final Map doricContextMap = new ConcurrentHashMap<>(); - public DoricSettableFuture invokeContextMethod(final String contextId, final String method, final Object... args) { + public AsyncResult invokeContextMethod(final String contextId, final String method, final Object... args) { return doricJSEngine.invokeContextEntityMethod(contextId, method, args); } @@ -36,15 +36,27 @@ public class DoricDriver { DoricContext createContext(final String script, final String source) { String contextId = String.valueOf(counter.incrementAndGet()); - doricJSEngine.prepareContext(contextId, script, source); DoricContext doricContext = new DoricContext(contextId); + doricJSEngine.prepareContext(contextId, script, source); doricContextMap.put(contextId, doricContext); return doricContext; } - void destroyContext(String contextId) { - doricContextMap.remove(contextId); - doricJSEngine.destroyContext(contextId); + void destroyContext(final String contextId) { + doricJSEngine.destroyContext(contextId).setCallback(new AsyncResult.Callback() { + @Override + public void onResult(Boolean result) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onFinish() { + doricContextMap.remove(contextId); + } + }); } public DoricContext getContext(String contextId) { diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/AsyncCall.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/AsyncCall.java new file mode 100644 index 00000000..e80bfc25 --- /dev/null +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/AsyncCall.java @@ -0,0 +1,37 @@ +package com.github.pengfeizhou.doric.async; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.Callable; + +/** + * @Description: com.github.pengfeizhou.doric.async + * @Author: pengfei.zhou + * @CreateDate: 2019-07-19 + */ +public class AsyncCall { + + public static AsyncResult ensureRunInHandler(Handler handler, final Callable callable) { + final AsyncResult asyncResult = new AsyncResult<>(); + if (Looper.myLooper() == handler.getLooper()) { + try { + asyncResult.setResult(callable.call()); + } catch (Exception e) { + asyncResult.setError(e); + } + } else { + handler.post(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/pengfeizhou/doric/async/AsyncResult.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/AsyncResult.java new file mode 100644 index 00000000..5ee471ec --- /dev/null +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/AsyncResult.java @@ -0,0 +1,70 @@ +package com.github.pengfeizhou.doric.async; + +/** + * @Description: com.github.pengfeizhou.doric.async + * @Author: pengfei.zhou + * @CreateDate: 2019-07-19 + */ +public class AsyncResult { + private static Object EMPTY = new Object(); + private Object result = EMPTY; + + private Callback callback = null; + + public void setResult(R result) { + this.result = result; + if (this.callback != null) { + this.callback.onResult(result); + this.callback.onFinish(); + } + } + + public void setError(Throwable result) { + this.result = result; + if (this.callback != null) { + this.callback.onError(result); + this.callback.onFinish(); + } + } + + public void setCallback(Callback callback) { + this.callback = callback; + if (result instanceof Throwable) { + this.callback.onError((Throwable) result); + this.callback.onFinish(); + } else if (result != EMPTY) { + this.callback.onResult((R) result); + this.callback.onFinish(); + } + } + + public SettableFuture synchronous() { + final SettableFuture settableFuture = new SettableFuture<>(); + + setCallback(new Callback() { + @Override + public void onResult(R result) { + settableFuture.set(result); + } + + @Override + public void onError(Throwable t) { + settableFuture.set(null); + } + + @Override + public void onFinish() { + + } + }); + return settableFuture; + } + + public interface Callback { + void onResult(R result); + + void onError(Throwable t); + + void onFinish(); + } +} diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricSettableFuture.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/SettableFuture.java similarity index 92% rename from Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricSettableFuture.java rename to Android/doric/src/main/java/com/github/pengfeizhou/doric/async/SettableFuture.java index 8ac927cd..c9561e2c 100644 --- a/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricSettableFuture.java +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/async/SettableFuture.java @@ -1,7 +1,7 @@ -package com.github.pengfeizhou.doric.utils; +package com.github.pengfeizhou.doric.async; /** - * @Description: Doric + * @Description: com.github.pengfeizhou.doric.async * @Author: pengfei.zhou * @CreateDate: 2019-07-18 */ @@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit; * A super simple Future-like class that can safely notify another Thread when a value is ready. * Does not support setting errors or canceling. */ -public class DoricSettableFuture { +public class SettableFuture { private final CountDownLatch mReadyLatch = new CountDownLatch(1); private volatile diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/engine/DoricJSEngine.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/engine/DoricJSEngine.java index 1f50d41d..7cfbef2b 100644 --- a/Android/doric/src/main/java/com/github/pengfeizhou/doric/engine/DoricJSEngine.java +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/engine/DoricJSEngine.java @@ -7,10 +7,12 @@ import android.os.Message; import android.text.TextUtils; import com.github.pengfeizhou.doric.Doric; +import com.github.pengfeizhou.doric.async.AsyncCall; import com.github.pengfeizhou.doric.extension.DoricBridgeExtension; +import com.github.pengfeizhou.doric.async.AsyncResult; import com.github.pengfeizhou.doric.utils.DoricConstant; import com.github.pengfeizhou.doric.utils.DoricLog; -import com.github.pengfeizhou.doric.utils.DoricSettableFuture; +import com.github.pengfeizhou.doric.async.SettableFuture; import com.github.pengfeizhou.doric.extension.DoricTimerExtension; import com.github.pengfeizhou.doric.utils.DoricUtils; import com.github.pengfeizhou.jscore.JSDecoder; @@ -18,6 +20,7 @@ import com.github.pengfeizhou.jscore.JavaFunction; import com.github.pengfeizhou.jscore.JavaValue; import java.util.ArrayList; +import java.util.concurrent.Callable; /** * @Description: Doric @@ -154,32 +157,34 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time mDoricJSE.loadJS(script, "Assets://" + assetName); } - public void prepareContext(final String contextId, final String script, final String source) { - Runnable runnable = new Runnable() { + public AsyncResult prepareContext(final String contextId, final String script, final String source) { + return AsyncCall.ensureRunInHandler(mJSHandler, new Callable() { @Override - public void run() { - mDoricJSE.loadJS(packageContextScript(contextId, script), "Context://" + source); + public Boolean call() throws Exception { + try { + mDoricJSE.loadJS(packageContextScript(contextId, script), "Context://" + source); + return true; + } catch (Exception e) { + DoricLog.e("Prepare Context error:%s", e.getLocalizedMessage()); + return false; + } } - }; - doOnJSThread(runnable); + }); } - public void doOnJSThread(Runnable runnable) { - if (isJSThread()) { - runnable.run(); - } else { - mJSHandler.post(runnable); - } - } - - public void destroyContext(final String contextId) { - Runnable runnable = new Runnable() { + public AsyncResult destroyContext(final String contextId) { + return AsyncCall.ensureRunInHandler(mJSHandler, new Callable() { @Override - public void run() { - mDoricJSE.loadJS(String.format(DoricConstant.TEMPLATE_CONTEXT_DESTROY, contextId), "_Context://" + contextId); + public Boolean call() throws Exception { + try { + mDoricJSE.loadJS(String.format(DoricConstant.TEMPLATE_CONTEXT_DESTROY, contextId), "_Context://" + contextId); + return true; + } catch (Exception e) { + DoricLog.e("Prepare Context error:%s", e.getLocalizedMessage()); + return false; + } } - }; - doOnJSThread(runnable); + }); } private String packageContextScript(String contextId, String content) { @@ -190,11 +195,7 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time return String.format(DoricConstant.TEMPLATE_MODULE, moduleName, content); } - public boolean isJSThread() { - return Looper.myLooper() == mJSHandler.getLooper(); - } - - public DoricSettableFuture invokeContextEntityMethod(final String contextId, final String method, final Object... args) { + public AsyncResult invokeContextEntityMethod(final String contextId, final String method, final Object... args) { final Object[] nArgs = new Object[args.length + 2]; nArgs[0] = contextId; nArgs[1] = method; @@ -205,21 +206,18 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time } - public DoricSettableFuture invokeDoricMethod(final String method, final Object... args) { - final DoricSettableFuture settableFuture = new DoricSettableFuture<>(); - Runnable runnable = new Runnable() { + public AsyncResult invokeDoricMethod(final String method, final Object... args) { + return AsyncCall.ensureRunInHandler(mJSHandler, new Callable() { @Override - public void run() { + public JSDecoder call() throws Exception { ArrayList values = new ArrayList<>(); for (Object arg : args) { values.add(DoricUtils.toJavaValue(arg)); } - settableFuture.set(mDoricJSE.invokeMethod(DoricConstant.GLOBAL_DORIC, method, - values.toArray(new JavaValue[values.size()]), true)); + return mDoricJSE.invokeMethod(DoricConstant.GLOBAL_DORIC, method, + values.toArray(new JavaValue[values.size()]), true); } - }; - doOnJSThread(runnable); - return settableFuture; + }); } @Override diff --git a/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricUtils.java b/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricUtils.java index d2656106..11c40c42 100644 --- a/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricUtils.java +++ b/Android/doric/src/main/java/com/github/pengfeizhou/doric/utils/DoricUtils.java @@ -1,6 +1,8 @@ package com.github.pengfeizhou.doric.utils; import android.content.res.AssetManager; +import android.os.Handler; +import android.os.Looper; import com.github.pengfeizhou.doric.Doric; import com.github.pengfeizhou.jscore.JavaValue; @@ -60,4 +62,5 @@ public class DoricUtils { return new JavaValue(String.valueOf(arg)); } } + }