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()
模拟按下物理按键
模拟按下物理按键
### Left()
模拟按下物理按键
模拟按下物理按键
### Right()
模拟按下物理按键
模拟按下物理按键
### OK()
模拟按下物理按键确定。

View File

@ -177,9 +177,9 @@ public class ScriptRuntime {
public void init() {
if (loopers != null)
throw new IllegalStateException("already initialized");
loopers = new Loopers();
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
timers = new Timers(bridges);
loopers = new Loopers(timers);
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
}
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.lang.ThreadCompat;
import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap;
/**
@ -14,26 +15,37 @@ import java.util.concurrent.ConcurrentHashMap;
public class Loopers {
public volatile boolean waitWhenIdle = false;
private volatile Looper mServantLooper;
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() {
public Loopers(Timers timers) {
mTimers = timers;
if (Looper.myLooper() == Looper.getMainLooper()) {
waitWhenIdle = true;
}
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
mMessageQueue = Looper.myQueue();
mMessageQueue.addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
Looper l = Looper.myLooper();
if (l != null && !waitWhenIdle)
if (l != null && shouldQuitLooper())
l.quit();
return true;
}
});
}
private boolean shouldQuitLooper() {
if (mTimers.hasPendingCallback()) {
return false;
}
return !waitWhenIdle;
}
private void initServantThread() {
new ThreadCompat(new Runnable() {

View File

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