package com.hdl.sdk.sourceos.utils.thread;
|
|
import android.os.Build;
|
import android.os.Handler;
|
import android.os.Looper;
|
import android.os.Message;
|
import android.os.MessageQueue;
|
|
import androidx.annotation.NonNull;
|
|
import java.lang.reflect.Method;
|
import java.util.LinkedList;
|
import java.util.concurrent.Executor;
|
|
|
/**
|
* Created by Tong on 2023/01/03.
|
*/
|
public class MainThreadExecutor implements Executor {
|
|
private final LinkedList<Runnable> mQueue = new LinkedList<>();
|
|
private final IdleHandlerImpl mHandler = new IdleHandlerImpl(Looper.getMainLooper());
|
|
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
private MessageQueue mMessageQueue;
|
|
private MainThreadExecutor() {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
mMessageQueue = Looper.getMainLooper().getQueue();
|
} else {
|
try {
|
Method getQueue = Looper.class.getDeclaredMethod("getQueue");
|
mMessageQueue = (MessageQueue) getQueue.invoke(Looper.getMainLooper());
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
private static class SingletonInstance {
|
private static final MainThreadExecutor INSTANCE = new MainThreadExecutor();
|
}
|
|
public static MainThreadExecutor getInstance() {
|
return SingletonInstance.INSTANCE;
|
}
|
|
|
private class IdleHandlerImpl extends Handler implements MessageQueue.IdleHandler {
|
|
public IdleHandlerImpl(@NonNull Looper looper) {
|
super(looper);
|
}
|
|
@Override
|
public void handleMessage(Message msg) {
|
Runnable r;
|
synchronized (mQueue) {
|
if (mQueue.size() == 0) {
|
return;
|
}
|
r = mQueue.removeFirst();
|
}
|
r.run();
|
synchronized (mQueue) {
|
scheduleNextLocked();
|
}
|
}
|
|
@Override
|
public boolean queueIdle() {
|
handleMessage(null);
|
//ture执行多次,false执行一次
|
return false;
|
}
|
}
|
|
private static class IdleRunnable implements Runnable {
|
Runnable mRunnable;
|
|
IdleRunnable(Runnable r) {
|
mRunnable = r;
|
}
|
|
public void run() {
|
mRunnable.run();
|
}
|
}
|
|
|
@Override
|
public void execute(Runnable command) {
|
if (Looper.getMainLooper() == Looper.myLooper()) {
|
command.run();
|
} else {
|
mainHandler.post(command);
|
}
|
}
|
|
|
public void post(Runnable runnable) {
|
synchronized (mQueue) {
|
mQueue.add(runnable);
|
if (mQueue.size() == 1) {
|
scheduleNextLocked();
|
}
|
}
|
}
|
|
public void postIdle(final Runnable runnable) {
|
post(new IdleRunnable(runnable));
|
}
|
|
public void postIdle(final Runnable runnable, long delayMillis) {
|
mHandler.postDelayed(runnable, delayMillis);
|
}
|
|
public void cancelAll() {
|
synchronized (mQueue) {
|
mQueue.clear();
|
}
|
}
|
|
public void flush() {
|
LinkedList<Runnable> queue;
|
synchronized (mQueue) {
|
queue = new LinkedList<>(mQueue);
|
mQueue.clear();
|
}
|
for (Runnable r : queue) {
|
r.run();
|
}
|
}
|
|
private void scheduleNextLocked() {
|
if (mQueue.size() > 0) {
|
Runnable peek = mQueue.getFirst();
|
if (peek instanceof IdleRunnable) {
|
if (mMessageQueue != null) {
|
mMessageQueue.addIdleHandler(mHandler);
|
}
|
|
} else {
|
mHandler.sendEmptyMessage(1);
|
}
|
}
|
}
|
|
|
}
|