Android: как перенести цикл сообщений в Activity, как GetMessage / PostMessage в Win32? - PullRequest
0 голосов
/ 31 мая 2011

Моя первоначальная цель - создать свой собственный модальный диалог. В какой-то момент мне нужно запустить внутренний цикл, который будет действительно близок к тому, что 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.

Если вам не важны проблемы с производительностью, это сработало.

1 Ответ

2 голосов
/ 31 мая 2011

Извините, Android сознательно не поддерживает подобные циклы вложенных событий.Вам просто нужно будет структурировать свой код другим способом - для диалогов вы обычно запускаете диалог, возвращаетесь в цикл обработки событий и внедряете обратные вызовы для обработки результата из него.

...