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"},
"negativeColor": {adapter: parseColor},
"cancelable": null,
"canceledOnTouchOutside": null
"canceledOnTouchOutside": null,
autoDismiss: null
};
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){
if(!properties.hasOwnProperty(name)){
continue;

View File

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

View File

@ -53,13 +53,35 @@ public class JsDialog {
private final EventEmitter mEmitter;
private final UiHandler mUiHandler;
private final MaterialDialog mDialog;
private final JsDialogBuilder mBuilder;
public JsDialog(MaterialDialog dialog, EventEmitter emitter, UiHandler uiHandler) {
mDialog = dialog;
public JsDialog(JsDialogBuilder builder, EventEmitter emitter, UiHandler uiHandler) {
mBuilder = builder;
mDialog = builder.build();
mEmitter = emitter;
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() {
return mDialog.getBuilder();
}
@ -695,22 +717,5 @@ public class JsDialog {
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.Theme;
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.ScriptRuntime;
import com.stardust.util.ArrayUtils;
import com.stardust.util.UiHandler;
@ -33,12 +37,18 @@ public class JsDialogBuilder extends MaterialDialog.Builder {
private final EventEmitter mEmitter;
private final UiHandler mUiHandler;
private final Timer mTimer;
private final Loopers mLoopers;
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);
mEmitter = new EventEmitter(bridges);
this.mUiHandler = uiHandler;
mTimer = runtime.timers.getTimerForCurrentThread();
mLoopers = runtime.loopers;
mEmitter = new EventEmitter(runtime.bridges, mTimer);
mUiHandler = runtime.uiHandler;
setUpEvents();
}
@ -64,16 +74,24 @@ public class JsDialogBuilder extends MaterialDialog.Builder {
break;
}
});
dismissListener(dialog -> emit("dismiss", dialog));
dismissListener(dialog -> {
mTimer.postDelayed(() -> mLoopers.doNotWaitWhenIdle(mWaitId), 0);
emit("dismiss", dialog);
});
cancelListener(dialog -> emit("cancel", dialog));
}
public void onShowCalled() {
mTimer.postDelayed(() -> mWaitId = mLoopers.waitWhenIdle(), 0);
}
public JsDialog getDialog() {
return mDialog;
}
public JsDialog buildDialog() {
mDialog = new JsDialog(super.build(), mEmitter, mUiHandler);
mDialog = new JsDialog(this, mEmitter, mUiHandler);
return mDialog;
}

View File

@ -212,7 +212,7 @@ public class ScriptRuntime {
images = new Images(context, this, builder.mScreenCaptureRequester);
}
engines = new Engines(builder.mEngineService, this);
dialogs = new Dialogs(app, uiHandler, bridges);
dialogs = new Dialogs(this);
device = new Device(context);
floaty = new Floaty(uiHandler, ui, 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.JsDialogBuilder;
import com.stardust.autojs.runtime.ScriptBridges;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.util.ArrayUtils;
import com.stardust.util.UiHandler;
@ -23,18 +24,14 @@ import com.stardust.util.UiHandler;
public class Dialogs {
private AppUtils mAppUtils;
private UiHandler mUiHandler;
private ContextThemeWrapper mThemeWrapper;
private ScriptBridges mScriptBridges;
private final ScriptRuntime mRuntime;
@ScriptVariable
public final NonUiDialogs nonUiDialogs = new NonUiDialogs();
public Dialogs(AppUtils appUtils, UiHandler uiHandler, ScriptBridges scriptBridges) {
mAppUtils = appUtils;
mUiHandler = uiHandler;
mScriptBridges = scriptBridges;
public Dialogs(ScriptRuntime runtime) {
mRuntime = runtime;
}
@ScriptInterface
@ -74,7 +71,7 @@ public class Dialogs {
private Context getContext() {
if (mThemeWrapper != null)
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;
}
@ -138,21 +135,21 @@ public class Dialogs {
private BlockedMaterialDialog.Builder dialogBuilder(Object callback) {
Context context = mAppUtils.getCurrentActivity();
Context context = mRuntime.app.getCurrentActivity();
if (context == null || ((Activity) context).isFinishing()) {
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);
}
@ScriptInterface
public MaterialDialog.Builder newBuilder() {
Context context = mAppUtils.getCurrentActivity();
Context context = mRuntime.app.getCurrentActivity();
if (context == null || ((Activity) context).isFinishing()) {
context = getContext();
}
return new JsDialogBuilder(context, mScriptBridges, mUiHandler)
return new JsDialogBuilder(context, mRuntime)
.theme(Theme.LIGHT);
}

View File

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