doric driver multiple instance

This commit is contained in:
王劲鹏 2019-11-22 11:30:14 +08:00
parent 32af5a2f77
commit 93cb80f6f8
10 changed files with 195 additions and 124 deletions

View File

@ -28,12 +28,10 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricDriver;
import pub.doric.dev.DevPanel; import pub.doric.dev.DevPanel;
import pub.doric.dev.SensorManagerHelper; import pub.doric.dev.SensorManagerHelper;
import pub.doric.dev.event.EnterDebugEvent; import pub.doric.dev.event.EnterDebugEvent;
import pub.doric.dev.event.QuitDebugEvent; import pub.doric.dev.event.QuitDebugEvent;
import pub.doric.engine.ChangeEngineCallback;
import pub.doric.utils.DoricUtils; import pub.doric.utils.DoricUtils;
/** /**
@ -98,32 +96,12 @@ public class DemoActivity extends AppCompatActivity {
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) { public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) {
DoricDriver.getInstance().changeJSEngine(false, new ChangeEngineCallback() { doricContext.startDebug();
@Override
public void changed() {
runOnUiThread(new Runnable() {
@Override
public void run() {
doricContext.init(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
});
}
});
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onQuitDebugEvent(QuitDebugEvent quitDebugEvent) { public void onQuitDebugEvent(QuitDebugEvent quitDebugEvent) {
DoricDriver.getInstance().changeJSEngine(true, new ChangeEngineCallback() { doricContext.stopDebug();
@Override
public void changed() {
runOnUiThread(new Runnable() {
@Override
public void run() {
doricContext.init(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
});
}
});
} }
@Override @Override

View File

@ -28,20 +28,11 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
import pub.doric.DoricDriver;
import pub.doric.dev.DevPanel; import pub.doric.dev.DevPanel;
import pub.doric.dev.event.EnterDebugEvent;
import pub.doric.dev.event.QuitDebugEvent;
import pub.doric.engine.ChangeEngineCallback;
import pub.doric.utils.DoricUtils; import pub.doric.utils.DoricUtils;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -57,7 +48,6 @@ public class MainActivity extends AppCompatActivity {
try { try {
String[] demos = getAssets().list("demo"); String[] demos = getAssets().list("demo");
List<String> ret = new ArrayList<>(); List<String> ret = new ArrayList<>();
ret.add("Debug Kit");
for (String str : demos) { for (String str : demos) {
if (str.endsWith("js")) { if (str.endsWith("js")) {
ret.add(str); ret.add(str);
@ -69,37 +59,6 @@ public class MainActivity extends AppCompatActivity {
} }
} }
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) {
DoricDriver.getInstance().changeJSEngine(false, new ChangeEngineCallback() {
@Override
public void changed() {
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onQuitDebugEvent(QuitDebugEvent quitDebugEvent) {
DoricDriver.getInstance().changeJSEngine(true, new ChangeEngineCallback() {
@Override
public void changed() {
}
});
}
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final String[] data; private final String[] data;

View File

@ -17,12 +17,6 @@ package pub.doric;
import android.content.Context; import android.content.Context;
import pub.doric.async.AsyncResult;
import pub.doric.plugin.DoricJavaPlugin;
import pub.doric.utils.DoricConstant;
import pub.doric.utils.DoricMetaInfo;
import pub.doric.shader.RootNode;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSONBuilder; import com.github.pengfeizhou.jscore.JSONBuilder;
@ -31,6 +25,13 @@ import org.json.JSONObject;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import pub.doric.async.AsyncResult;
import pub.doric.engine.IStatusCallback;
import pub.doric.plugin.DoricJavaPlugin;
import pub.doric.shader.RootNode;
import pub.doric.utils.DoricConstant;
import pub.doric.utils.DoricMetaInfo;
/** /**
* @Description: Doric * @Description: Doric
* @Author: pengfei.zhou * @Author: pengfei.zhou
@ -44,6 +45,8 @@ public class DoricContext {
private final String source; private final String source;
private String script; private String script;
private JSONObject initParams; private JSONObject initParams;
public boolean isDebugging = false;
private DoricDebugDriver doricDebugDriver;
DoricContext(Context context, String contextId, String source) { DoricContext(Context context, String contextId, String source) {
this.mContext = context; this.mContext = context;
@ -79,7 +82,11 @@ public class DoricContext {
} }
public IDoricDriver getDriver() { public IDoricDriver getDriver() {
return DoricDriver.getInstance(); if (isDebugging) {
return doricDebugDriver;
} else {
return DoricNativeDriver.getInstance();
}
} }
public RootNode getRootNode() { public RootNode getRootNode() {
@ -136,4 +143,21 @@ public class DoricContext {
public void onHidden() { public void onHidden() {
callEntity(DoricConstant.DORIC_ENTITY_HIDDEN); callEntity(DoricConstant.DORIC_ENTITY_HIDDEN);
} }
public void startDebug() {
doricDebugDriver = new DoricDebugDriver(new IStatusCallback() {
@Override
public void start() {
isDebugging=true;
callEntity(DoricConstant.DORIC_ENTITY_INIT, initParams);
callEntity(DoricConstant.DORIC_ENTITY_CREATE);
}
});
}
public void stopDebug() {
isDebugging = false;
callEntity(DoricConstant.DORIC_ENTITY_INIT, initParams);
callEntity(DoricConstant.DORIC_ENTITY_CREATE);
}
} }

View File

@ -0,0 +1,129 @@
/*
* Copyright [2019] [Doric.Pub]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package pub.doric;
import android.os.Handler;
import android.os.Looper;
import com.github.pengfeizhou.jscore.JSDecoder;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import pub.doric.async.AsyncCall;
import pub.doric.async.AsyncResult;
import pub.doric.engine.DoricJSEngine;
import pub.doric.engine.IStatusCallback;
import pub.doric.utils.DoricConstant;
import pub.doric.utils.DoricLog;
import pub.doric.utils.ThreadMode;
/**
* @Description: Doric
* @Author: pengfei.zhou
* @CreateDate: 2019-07-18
*/
public class DoricDebugDriver implements IDoricDriver {
private final DoricJSEngine doricJSEngine;
private final ExecutorService mBridgeExecutor;
private final Handler mUIHandler;
private final Handler mJSHandler;
public DoricDebugDriver(IStatusCallback statusCallback) {
doricJSEngine = new DoricJSEngine(false, statusCallback);
mBridgeExecutor = Executors.newCachedThreadPool();
mUIHandler = new Handler(Looper.getMainLooper());
mJSHandler = doricJSEngine.getJSHandler();
}
@Override
public AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) {
final Object[] nArgs = new Object[args.length + 2];
nArgs[0] = contextId;
nArgs[1] = method;
if (args.length > 0) {
System.arraycopy(args, 0, nArgs, 2, args.length);
}
return invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE, nArgs);
}
@Override
public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
@Override
public JSDecoder call() {
try {
return doricJSEngine.invokeDoricMethod(method, args);
} catch (Exception e) {
DoricLog.e("invokeDoricMethod(%s,...),error is %s", method, e.getLocalizedMessage());
return new JSDecoder(null);
}
}
});
}
@Override
public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
switch (threadMode) {
case JS:
return AsyncCall.ensureRunInHandler(mJSHandler, callable);
case UI:
return AsyncCall.ensureRunInHandler(mUIHandler, callable);
case INDEPENDENT:
default:
return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
}
}
@Override
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
@Override
public Boolean call() {
try {
doricJSEngine.prepareContext(contextId, script, source);
return true;
} catch (Exception e) {
DoricLog.e("createContext %s error is %s", source, e.getLocalizedMessage());
return false;
}
}
});
}
@Override
public AsyncResult<Boolean> destroyContext(final String contextId) {
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
@Override
public Boolean call() {
try {
doricJSEngine.destroyContext(contextId);
return true;
} catch (Exception e) {
DoricLog.e("destroyContext %s error is %s", contextId, e.getLocalizedMessage());
return false;
}
}
});
}
@Override
public DoricRegistry getRegistry() {
return doricJSEngine.getRegistry();
}
}

View File

@ -26,7 +26,6 @@ import java.util.concurrent.Executors;
import pub.doric.async.AsyncCall; import pub.doric.async.AsyncCall;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.engine.ChangeEngineCallback;
import pub.doric.engine.DoricJSEngine; import pub.doric.engine.DoricJSEngine;
import pub.doric.utils.DoricConstant; import pub.doric.utils.DoricConstant;
import pub.doric.utils.DoricLog; import pub.doric.utils.DoricLog;
@ -37,12 +36,27 @@ import pub.doric.utils.ThreadMode;
* @Author: pengfei.zhou * @Author: pengfei.zhou
* @CreateDate: 2019-07-18 * @CreateDate: 2019-07-18
*/ */
public class DoricDriver implements IDoricDriver { public class DoricNativeDriver implements IDoricDriver {
private final DoricJSEngine doricJSEngine; private final DoricJSEngine doricJSEngine;
private final ExecutorService mBridgeExecutor; private final ExecutorService mBridgeExecutor;
private final Handler mUIHandler; private final Handler mUIHandler;
private final Handler mJSHandler; private final Handler mJSHandler;
private static class Inner {
private static final DoricNativeDriver sInstance = new DoricNativeDriver();
}
private DoricNativeDriver() {
doricJSEngine = new DoricJSEngine(true, null);
mBridgeExecutor = Executors.newCachedThreadPool();
mUIHandler = new Handler(Looper.getMainLooper());
mJSHandler = doricJSEngine.getJSHandler();
}
public static DoricNativeDriver getInstance() {
return Inner.sInstance;
}
@Override @Override
public AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) { public AsyncResult<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) {
final Object[] nArgs = new Object[args.length + 2]; final Object[] nArgs = new Object[args.length + 2];
@ -82,23 +96,6 @@ public class DoricDriver implements IDoricDriver {
} }
} }
private static class Inner {
private static final DoricDriver sInstance = new DoricDriver();
}
private DoricDriver() {
doricJSEngine = new DoricJSEngine();
mBridgeExecutor = Executors.newCachedThreadPool();
mUIHandler = new Handler(Looper.getMainLooper());
mJSHandler = doricJSEngine.getJSHandler();
}
public static DoricDriver getInstance() {
return Inner.sInstance;
}
@Override @Override
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) { public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() { return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
@ -135,8 +132,4 @@ public class DoricDriver implements IDoricDriver {
public DoricRegistry getRegistry() { public DoricRegistry getRegistry() {
return doricJSEngine.getRegistry(); return doricJSEngine.getRegistry();
} }
public void changeJSEngine(boolean isNative, ChangeEngineCallback changeEngineCallback) {
doricJSEngine.changeJSEngine(isNative, changeEngineCallback);
}
} }

View File

@ -1,5 +0,0 @@
package pub.doric.engine;
public interface ChangeEngineCallback {
void changed();
}

View File

@ -43,11 +43,10 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
private final Handler mJSHandler; private final Handler mJSHandler;
private final DoricBridgeExtension mDoricBridgeExtension = new DoricBridgeExtension(); private final DoricBridgeExtension mDoricBridgeExtension = new DoricBridgeExtension();
private IDoricJSE mDoricJSE; private IDoricJSE mDoricJSE;
private DoricNativeJSExecutor doricNativeJSExecutor;
private final DoricTimerExtension mTimerExtension; private final DoricTimerExtension mTimerExtension;
private final DoricRegistry mDoricRegistry = new DoricRegistry(); private final DoricRegistry mDoricRegistry = new DoricRegistry();
public DoricJSEngine() { public DoricJSEngine(final boolean isNative, final IStatusCallback statusCallback) {
HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName()); HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName());
handlerThread.start(); handlerThread.start();
Looper looper = handlerThread.getLooper(); Looper looper = handlerThread.getLooper();
@ -55,9 +54,12 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
mJSHandler.post(new Runnable() { mJSHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
doricNativeJSExecutor = new DoricNativeJSExecutor(); if (isNative) {
mDoricJSE = new DoricNativeJSExecutor();
} else {
mDoricJSE = new DoricRemoteJSExecutor(statusCallback);
}
mDoricJSE = doricNativeJSExecutor;
injectGlobal(); injectGlobal();
initDoricRuntime(); initDoricRuntime();
} }
@ -213,20 +215,4 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
public DoricRegistry getRegistry() { public DoricRegistry getRegistry() {
return mDoricRegistry; return mDoricRegistry;
} }
public void changeJSEngine(final boolean isNative, final ChangeEngineCallback changeEngineCallback) {
mJSHandler.post(new Runnable() {
@Override
public void run() {
if (isNative) {
mDoricJSE.teardown();
mDoricJSE = doricNativeJSExecutor;
} else {
mDoricJSE = new DoricRemoteJSExecutor();
injectGlobal();
}
changeEngineCallback.changed();
}
});
}
} }

View File

@ -26,8 +26,8 @@ public class DoricRemoteJSExecutor implements IDoricJSE {
private final RemoteJSExecutor mRemoteJSExecutor; private final RemoteJSExecutor mRemoteJSExecutor;
public DoricRemoteJSExecutor() { public DoricRemoteJSExecutor(IStatusCallback statusCallback) {
this.mRemoteJSExecutor = new RemoteJSExecutor(); this.mRemoteJSExecutor = new RemoteJSExecutor(statusCallback);
} }
@Override @Override

View File

@ -0,0 +1,5 @@
package pub.doric.engine;
public interface IStatusCallback {
void start();
}

View File

@ -25,13 +25,14 @@ import okhttp3.WebSocket;
import okhttp3.WebSocketListener; import okhttp3.WebSocketListener;
import pub.doric.dev.DevKit; import pub.doric.dev.DevKit;
import pub.doric.dev.event.QuitDebugEvent; import pub.doric.dev.event.QuitDebugEvent;
import pub.doric.engine.IStatusCallback;
public class RemoteJSExecutor { public class RemoteJSExecutor {
private final WebSocket webSocket; private final WebSocket webSocket;
private final Map<String, JavaFunction> globalFunctions = new HashMap<>(); private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
private JSDecoder temp; private JSDecoder temp;
public RemoteJSExecutor() { public RemoteJSExecutor(final IStatusCallback statusCallback) {
OkHttpClient okHttpClient = new OkHttpClient OkHttpClient okHttpClient = new OkHttpClient
.Builder() .Builder()
.readTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS)
@ -44,6 +45,7 @@ public class RemoteJSExecutor {
@Override @Override
public void onOpen(WebSocket webSocket, Response response) { public void onOpen(WebSocket webSocket, Response response) {
LockSupport.unpark(current); LockSupport.unpark(current);
statusCallback.start();
} }
@Override @Override