api(dialogs): change dialog event callback thread to caller thread

This commit is contained in:
hyb1996
2018-04-18 17:48:26 +08:00
parent 97198ad668
commit baaa820d09
7 changed files with 80 additions and 41 deletions

View File

@@ -119,11 +119,13 @@ module.exports = function(__runtime__, scope){
"negative": {method: "negativeText"}, "negative": {method: "negativeText"},
"negativeColor": {adapter: parseColor}, "negativeColor": {adapter: parseColor},
"cancelable": null, "cancelable": null,
"canceledOnTouchOutside": null "canceledOnTouchOutside": null,
autoDismiss: null
}; };
dialogs.build = function(properties){ dialogs.build = function(properties){
var builder = __runtime__.dialogs.newBuilder(); var builder = Object.create(__runtime__.dialogs.newBuilder());
builder.thread = threads.currentThread();
for(var name in properties){ for(var name in properties){
if(!properties.hasOwnProperty(name)){ if(!properties.hasOwnProperty(name)){
continue; continue;

View File

@@ -5,12 +5,14 @@ import android.os.Looper;
import android.os.MessageQueue; import android.os.MessageQueue;
import android.util.Log; import android.util.Log;
import com.android.dx.util.IntSet;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.Threads; import com.stardust.autojs.runtime.api.Threads;
import com.stardust.autojs.runtime.api.Timers; import com.stardust.autojs.runtime.api.Timers;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.lang.ThreadCompat; import com.stardust.lang.ThreadCompat;
import java.util.HashSet;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/** /**
@@ -29,6 +31,8 @@ public class Loopers implements MessageQueue.IdleHandler {
}; };
private volatile ThreadLocal<Boolean> waitWhenIdle = new ThreadLocal<>(); private volatile ThreadLocal<Boolean> waitWhenIdle = new ThreadLocal<>();
private volatile ThreadLocal<HashSet<Integer>> waitIds = new ThreadLocal<>();
private volatile ThreadLocal<Integer> maxWaitId = new ThreadLocal<>();
private volatile ThreadLocal<CopyOnWriteArrayList<LooperQuitHandler>> looperQuitHanders = new ThreadLocal<>(); private volatile ThreadLocal<CopyOnWriteArrayList<LooperQuitHandler>> looperQuitHanders = new ThreadLocal<>();
private volatile Looper mServantLooper; private volatile Looper mServantLooper;
private Timers mTimers; private Timers mTimers;
@@ -75,7 +79,7 @@ public class Loopers implements MessageQueue.IdleHandler {
if (mTimers.hasPendingCallbacks()) { if (mTimers.hasPendingCallbacks()) {
return false; return false;
} }
if (waitWhenIdle.get()) { if (waitWhenIdle.get() || !waitIds.get().isEmpty()) {
return false; return false;
} }
CopyOnWriteArrayList<LooperQuitHandler> handlers = looperQuitHanders.get(); CopyOnWriteArrayList<LooperQuitHandler> handlers = looperQuitHanders.get();
@@ -123,6 +127,17 @@ public class Loopers implements MessageQueue.IdleHandler {
mServantLooper.quit(); mServantLooper.quit();
} }
public int waitWhenIdle() {
int id = maxWaitId.get();
maxWaitId.set(id + 1);
waitIds.get().add(id);
return id;
}
public void doNotWaitWhenIdle(int waitId) {
waitIds.get().remove(waitId);
}
public void waitWhenIdle(boolean b) { public void waitWhenIdle(boolean b) {
waitWhenIdle.set(b); waitWhenIdle.set(b);
} }
@@ -162,6 +177,8 @@ public class Loopers implements MessageQueue.IdleHandler {
LooperHelper.prepare(); LooperHelper.prepare();
Looper.myQueue().addIdleHandler(this); Looper.myQueue().addIdleHandler(this);
waitWhenIdle.set(Looper.myLooper() == Looper.getMainLooper()); waitWhenIdle.set(Looper.myLooper() == Looper.getMainLooper());
waitIds.set(new HashSet<>());
maxWaitId.set(0);
} }
public void notifyThreadExit(TimerThread thread) { public void notifyThreadExit(TimerThread thread) {

View File

@@ -53,13 +53,35 @@ public class JsDialog {
private final EventEmitter mEmitter; private final EventEmitter mEmitter;
private final UiHandler mUiHandler; private final UiHandler mUiHandler;
private final MaterialDialog mDialog; private final MaterialDialog mDialog;
private final JsDialogBuilder mBuilder;
public JsDialog(MaterialDialog dialog, EventEmitter emitter, UiHandler uiHandler) { public JsDialog(JsDialogBuilder builder, EventEmitter emitter, UiHandler uiHandler) {
mDialog = dialog; mBuilder = builder;
mDialog = builder.build();
mEmitter = emitter; mEmitter = emitter;
mUiHandler = uiHandler; mUiHandler = uiHandler;
} }
public JsDialog show() {
checkWindowType();
if (Looper.myLooper() == Looper.getMainLooper()) {
mDialog.show();
} else {
mUiHandler.post(mDialog::show);
}
mBuilder.onShowCalled();
return this;
}
private void checkWindowType() {
Context context = mDialog.getContext();
if (!DialogUtils.isActivityContext(context)) {
Window window = mDialog.getWindow();
if (window != null)
window.setType(WindowManager.LayoutParams.TYPE_PHONE);
}
}
public MaterialDialog.Builder getBuilder() { public MaterialDialog.Builder getBuilder() {
return mDialog.getBuilder(); return mDialog.getBuilder();
} }
@@ -695,22 +717,5 @@ public class JsDialog {
return EventEmitter.defaultMaxListeners(); return EventEmitter.defaultMaxListeners();
} }
public JsDialog show() {
checkWindowType();
if (Looper.myLooper() == Looper.getMainLooper()) {
mDialog.show();
} else {
mUiHandler.post(mDialog::show);
}
return this;
}
private void checkWindowType() {
Context context = mDialog.getContext();
if (!DialogUtils.isActivityContext(context)) {
Window window = mDialog.getWindow();
if (window != null)
window.setType(WindowManager.LayoutParams.TYPE_PHONE);
}
}
} }

View File

@@ -18,7 +18,11 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.StackingBehavior; import com.afollestad.materialdialogs.StackingBehavior;
import com.afollestad.materialdialogs.Theme; import com.afollestad.materialdialogs.Theme;
import com.stardust.autojs.core.eventloop.EventEmitter; import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.looper.Loopers;
import com.stardust.autojs.core.looper.Timer;
import com.stardust.autojs.core.looper.TimerThread;
import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptBridges;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.util.ArrayUtils; import com.stardust.util.ArrayUtils;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
@@ -33,12 +37,18 @@ public class JsDialogBuilder extends MaterialDialog.Builder {
private final EventEmitter mEmitter; private final EventEmitter mEmitter;
private final UiHandler mUiHandler; private final UiHandler mUiHandler;
private final Timer mTimer;
private final Loopers mLoopers;
private JsDialog mDialog; private JsDialog mDialog;
private volatile int mWaitId = -1;
public JsDialogBuilder(@NonNull Context context, ScriptBridges bridges, UiHandler uiHandler) {
public JsDialogBuilder(Context context, ScriptRuntime runtime) {
super(context); super(context);
mEmitter = new EventEmitter(bridges); mTimer = runtime.timers.getTimerForCurrentThread();
this.mUiHandler = uiHandler; mLoopers = runtime.loopers;
mEmitter = new EventEmitter(runtime.bridges, mTimer);
mUiHandler = runtime.uiHandler;
setUpEvents(); setUpEvents();
} }
@@ -64,16 +74,24 @@ public class JsDialogBuilder extends MaterialDialog.Builder {
break; break;
} }
}); });
dismissListener(dialog -> emit("dismiss", dialog)); dismissListener(dialog -> {
mTimer.postDelayed(() -> mLoopers.doNotWaitWhenIdle(mWaitId), 0);
emit("dismiss", dialog);
});
cancelListener(dialog -> emit("cancel", dialog)); cancelListener(dialog -> emit("cancel", dialog));
} }
public void onShowCalled() {
mTimer.postDelayed(() -> mWaitId = mLoopers.waitWhenIdle(), 0);
}
public JsDialog getDialog() { public JsDialog getDialog() {
return mDialog; return mDialog;
} }
public JsDialog buildDialog() { public JsDialog buildDialog() {
mDialog = new JsDialog(super.build(), mEmitter, mUiHandler); mDialog = new JsDialog(this, mEmitter, mUiHandler);
return mDialog; return mDialog;
} }

View File

@@ -212,7 +212,7 @@ public class ScriptRuntime {
images = new Images(context, this, builder.mScreenCaptureRequester); images = new Images(context, this, builder.mScreenCaptureRequester);
} }
engines = new Engines(builder.mEngineService, this); engines = new Engines(builder.mEngineService, this);
dialogs = new Dialogs(app, uiHandler, bridges); dialogs = new Dialogs(this);
device = new Device(context); device = new Device(context);
floaty = new Floaty(uiHandler, ui, this); floaty = new Floaty(uiHandler, ui, this);
files = new Files(this); files = new Files(this);

View File

@@ -14,6 +14,7 @@ import com.stardust.autojs.annotation.ScriptVariable;
import com.stardust.autojs.core.ui.dialog.BlockedMaterialDialog; import com.stardust.autojs.core.ui.dialog.BlockedMaterialDialog;
import com.stardust.autojs.core.ui.dialog.JsDialogBuilder; import com.stardust.autojs.core.ui.dialog.JsDialogBuilder;
import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptBridges;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.util.ArrayUtils; import com.stardust.util.ArrayUtils;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
@@ -23,18 +24,14 @@ import com.stardust.util.UiHandler;
public class Dialogs { public class Dialogs {
private AppUtils mAppUtils;
private UiHandler mUiHandler;
private ContextThemeWrapper mThemeWrapper; private ContextThemeWrapper mThemeWrapper;
private ScriptBridges mScriptBridges; private final ScriptRuntime mRuntime;
@ScriptVariable @ScriptVariable
public final NonUiDialogs nonUiDialogs = new NonUiDialogs(); public final NonUiDialogs nonUiDialogs = new NonUiDialogs();
public Dialogs(AppUtils appUtils, UiHandler uiHandler, ScriptBridges scriptBridges) { public Dialogs(ScriptRuntime runtime) {
mAppUtils = appUtils; mRuntime = runtime;
mUiHandler = uiHandler;
mScriptBridges = scriptBridges;
} }
@ScriptInterface @ScriptInterface
@@ -74,7 +71,7 @@ public class Dialogs {
private Context getContext() { private Context getContext() {
if (mThemeWrapper != null) if (mThemeWrapper != null)
return mThemeWrapper; return mThemeWrapper;
mThemeWrapper = new ContextThemeWrapper(mUiHandler.getContext().getApplicationContext(), R.style.Theme_AppCompat_Light); mThemeWrapper = new ContextThemeWrapper(mRuntime.uiHandler.getContext().getApplicationContext(), R.style.Theme_AppCompat_Light);
return mThemeWrapper; return mThemeWrapper;
} }
@@ -138,21 +135,21 @@ public class Dialogs {
private BlockedMaterialDialog.Builder dialogBuilder(Object callback) { private BlockedMaterialDialog.Builder dialogBuilder(Object callback) {
Context context = mAppUtils.getCurrentActivity(); Context context = mRuntime.app.getCurrentActivity();
if (context == null || ((Activity) context).isFinishing()) { if (context == null || ((Activity) context).isFinishing()) {
context = getContext(); context = getContext();
} }
return (BlockedMaterialDialog.Builder) new BlockedMaterialDialog.Builder(context, mUiHandler, mScriptBridges, callback) return (BlockedMaterialDialog.Builder) new BlockedMaterialDialog.Builder(context, mRuntime.uiHandler, mRuntime.bridges, callback)
.theme(Theme.LIGHT); .theme(Theme.LIGHT);
} }
@ScriptInterface @ScriptInterface
public MaterialDialog.Builder newBuilder() { public MaterialDialog.Builder newBuilder() {
Context context = mAppUtils.getCurrentActivity(); Context context = mRuntime.app.getCurrentActivity();
if (context == null || ((Activity) context).isFinishing()) { if (context == null || ((Activity) context).isFinishing()) {
context = getContext(); context = getContext();
} }
return new JsDialogBuilder(context, mScriptBridges, mUiHandler) return new JsDialogBuilder(context, mRuntime)
.theme(Theme.LIGHT); .theme(Theme.LIGHT);
} }

View File

@@ -39,7 +39,7 @@ public class Timers {
return mMaxCallbackUptimeMillisForAllThreads; return mMaxCallbackUptimeMillisForAllThreads;
} }
private Timer getTimerForCurrentThread() { public Timer getTimerForCurrentThread() {
return getTimerForThread(Thread.currentThread()); return getTimerForThread(Thread.currentThread());
} }