Моя первоначальная цель - создать свой собственный модальный диалог. В какой-то момент мне нужно запустить внутренний цикл, который будет действительно близок к тому, что GetMessage / PostMessage делает в Win32, если у вас есть опыт работы с Win32, то вы хорошо знакомы с этим. Внутренний цикл заблокирует текущий рабочий процесс, но все еще обрабатывает события . Псевдокод будет выглядеть так:
private void doModal() {
doSth();
// start loop and process events
while (!isQuit) {
Message msg = nextMessage();
// process all wanted msgs, and simply discard all unexpected msgs
if (isWantedMsg) {
sendToTarget(msg);
}
}
}
Я изучил исходный код Looper.loop (), который был
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}
По сути, я хотел бы написать такой цикл, тогда я смогу получать все сообщения и обрабатывать или удалять их соответственно. К сожалению, MessageQueue принадлежит пакету android.os, у меня нет привилегий для доступа к большинству его интерфейсов. Activity.dispatchTouchEvent - это просто обработчик, а не мой случай.
Как я мог это сделать? Спасибо.
========================== РЕШЕНИЕ ==================== =================
Я решил это отражением, я точно скопировал источник Looper.loop (), см. Ниже,
private void startModal() {
Class clsMsgQueue = null;
Method nextMethod = null;
Class clsMsg = null;
mQuitModal = false;
MessageQueue queue = Looper.myQueue();
clsMsgQueue = queue.getClass();
try {
nextMethod = clsMsgQueue.getDeclaredMethod("next", new Class[]{});
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
nextMethod.setAccessible(true);
while (!mQuitModal) {
Message msg = null;
try {
msg = (Message)nextMethod.invoke(queue, new Object[]{});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (msg != null) {
clsMsg = msg.getClass();
Field targetFiled = null;
try {
targetFiled = clsMsg.getDeclaredField("target");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
targetFiled.setAccessible(true);
Handler target = null;
try {
target = (Handler) targetFiled.get(msg);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (target == null) {
// No target is a magic identifier for the quit message.
mQuitModal = true;
}
target.dispatchMessage(msg);
msg.recycle();
}
}
}
Когда диалоговое окно было закрыто, для mQuitModal также было установлено значение true.
Если вам не важны проблемы с производительностью, это сработало.