fix: setInterval & setTimeout not working when waitWhenIdle is false

This commit is contained in:
hyb1996
2017-08-15 21:12:58 +08:00
parent 197f2136c6
commit 7b1a5fc675
4 changed files with 54 additions and 32 deletions

View File

@@ -58,13 +58,13 @@ for(var i = 0; i < 100; i++){
模拟按下物理按键上。 模拟按下物理按键上。
### Down() ### Down()
模拟按下物理按键 模拟按下物理按键
### Left() ### Left()
模拟按下物理按键 模拟按下物理按键
### Right() ### Right()
模拟按下物理按键 模拟按下物理按键
### OK() ### OK()
模拟按下物理按键确定。 模拟按下物理按键确定。

View File

@@ -177,9 +177,9 @@ public class ScriptRuntime {
public void init() { public void init() {
if (loopers != null) if (loopers != null)
throw new IllegalStateException("already initialized"); throw new IllegalStateException("already initialized");
loopers = new Loopers();
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
timers = new Timers(bridges); timers = new Timers(bridges);
loopers = new Loopers(timers);
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
} }
public static void setApplicationContext(Context context) { public static void setApplicationContext(Context context) {

View File

@@ -6,6 +6,7 @@ import android.os.MessageQueue;
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.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@@ -14,26 +15,37 @@ import java.util.concurrent.ConcurrentHashMap;
public class Loopers { public class Loopers {
public volatile boolean waitWhenIdle = false;
private volatile Looper mServantLooper; private volatile Looper mServantLooper;
private static volatile ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>(); private static volatile ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
private static Field MESSAGE_QUEUE_MESSAGE;
private Timers mTimers;
private MessageQueue mMessageQueue;
public volatile boolean waitWhenIdle = false; public Loopers(Timers timers) {
mTimers = timers;
public Loopers() {
if (Looper.myLooper() == Looper.getMainLooper()) { if (Looper.myLooper() == Looper.getMainLooper()) {
waitWhenIdle = true; waitWhenIdle = true;
} }
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { mMessageQueue = Looper.myQueue();
mMessageQueue.addIdleHandler(new MessageQueue.IdleHandler() {
@Override @Override
public boolean queueIdle() { public boolean queueIdle() {
Looper l = Looper.myLooper(); Looper l = Looper.myLooper();
if (l != null && !waitWhenIdle) if (l != null && shouldQuitLooper())
l.quit(); l.quit();
return true; return true;
} }
}); });
} }
private boolean shouldQuitLooper() {
if (mTimers.hasPendingCallback()) {
return false;
}
return !waitWhenIdle;
}
private void initServantThread() { private void initServantThread() {
new ThreadCompat(new Runnable() { new ThreadCompat(new Runnable() {

View File

@@ -1,6 +1,7 @@
package com.stardust.autojs.runtime.api; package com.stardust.autojs.runtime.api;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock;
import android.util.SparseArray; import android.util.SparseArray;
import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptBridges;
@@ -15,19 +16,20 @@ public class Timers {
private int mCallbackMaxId = 0; private int mCallbackMaxId = 0;
private ScriptBridges mBridges; private ScriptBridges mBridges;
private Handler mHandler; private Handler mHandler;
private long mFutureCallbackUptimeMillis = 0;
public Timers(ScriptBridges bridges) { public Timers(ScriptBridges bridges) {
mBridges = bridges; mBridges = bridges;
} }
private void ensureHander(){ private void ensureHandler() {
if(mHandler == null){ if (mHandler == null) {
mHandler = new Handler(); mHandler = new Handler();
} }
} }
public int setTimeout(final Object callback, long delay, final Object... args) { public int setTimeout(final Object callback, long delay, final Object... args) {
ensureHander(); ensureHandler();
mCallbackMaxId++; mCallbackMaxId++;
final int id = mCallbackMaxId; final int id = mCallbackMaxId;
Runnable r = new Runnable() { Runnable r = new Runnable() {
@@ -38,41 +40,44 @@ public class Timers {
} }
}; };
mHandlerCallbacks.put(id, r); mHandlerCallbacks.put(id, r);
mHandler.postDelayed(r, delay); postDelayed(r, delay);
return id; return id;
} }
public void post(Runnable r) { public boolean clearTimeout(int id) {
ensureHander(); return clearCallback(id);
mHandler.post(r);
}
public void clearTimeout(int id) {
clearCallback(id);
} }
public int setInterval(final Object listener, final long interval, final Object... args) { public int setInterval(final Object listener, final long interval, final Object... args) {
ensureHander(); ensureHandler();
mCallbackMaxId++; mCallbackMaxId++;
final int id = mCallbackMaxId; final int id = mCallbackMaxId;
Runnable r = new Runnable() { final Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {
if (mHandlerCallbacks.get(id) == null)
return;
mBridges.callFunction(listener, null, args); mBridges.callFunction(listener, null, args);
mHandler.postDelayed(this, interval); postDelayed(this, interval);
} }
}; };
mHandlerCallbacks.put(id, r); mHandlerCallbacks.put(id, r);
mHandler.postDelayed(r, interval); postDelayed(r, interval);
return id; return id;
} }
public void clearInterval(int id) { private void postDelayed(Runnable r, long interval) {
clearTimeout(id); long uptime = SystemClock.uptimeMillis() + interval;
mHandler.postAtTime(r, uptime);
mFutureCallbackUptimeMillis = Math.max(mFutureCallbackUptimeMillis, uptime);
}
public boolean clearInterval(int id) {
return clearCallback(id);
} }
public int setImmediate(final Object listener, final Object... args) { public int setImmediate(final Object listener, final Object... args) {
ensureHander(); ensureHandler();
mCallbackMaxId++; mCallbackMaxId++;
final int id = mCallbackMaxId; final int id = mCallbackMaxId;
Runnable r = new Runnable() { Runnable r = new Runnable() {
@@ -83,21 +88,26 @@ public class Timers {
} }
}; };
mHandlerCallbacks.put(id, r); mHandlerCallbacks.put(id, r);
mHandler.post(r); postDelayed(r, 0);
return id; return id;
} }
public void clearImmediate(int id) { public boolean clearImmediate(int id) {
clearCallback(id); return clearCallback(id);
} }
private void clearCallback(int id) { private boolean clearCallback(int id) {
Runnable callback = mHandlerCallbacks.get(id); Runnable callback = mHandlerCallbacks.get(id);
if (callback != null) { if (callback != null) {
mHandler.removeCallbacks(callback); mHandler.removeCallbacks(callback);
mHandlerCallbacks.remove(id); mHandlerCallbacks.remove(id);
return true;
} }
return false;
} }
public boolean hasPendingCallback() {
return mFutureCallbackUptimeMillis > SystemClock.uptimeMillis();
}
} }