Нужна помощь с обратными вызовами и анонимными классами в Java - PullRequest
6 голосов
/ 28 мая 2009

Я использую какую-то стороннюю библиотеку для подключения к серверу по асинхронному протоколу и получения ответа обратно. Например, метод получения идентификатора пользователя по имени выглядит так:

public int getUserid(String username) {
        int userid = 0;

    connection.call("getUserid", new Responder() {
        public void onResult(final int result) {
            System.out.println("userid: " + result);
            //how to assign received value to userid and return it?
        }
    }, username);

    //wait for response
    while (userid == 0) {
            try{
                Thread.sleep(100);
            } catch (Exception e) {}
        }


        return userid;
}

Проблема в том, что я не могу присвоить возвращенный «результат» из ответа сервера переменной «userid» из метода (чтобы вернуть его после). Как это решить? Я, вероятно, могу назначить его некоторой переменной класса, а не переменной метода, но я хочу оставить ее в области действия метода, чтобы мне не приходилось сталкиваться с проблемами параллелизма.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 28 мая 2009

Если я правильно понимаю ваш вопрос, вы спрашиваете, как написать переменную внутри анонимного класса.

Анонимные классы могут обращаться только к конечным переменным и не могут напрямую «записывать» их.

Простое решение, которое является "достаточно хорошим", заключается в создании своего рода класса ValueBox с одним полем значения, а также с геттером и сеттером. Затем вы можете создать экземпляр новой функции в качестве конечной переменной и получить к ней доступ от анонимного класса. Анонимный класс будет использовать свои методы получения и записи для записи / чтения.

Тот факт, что переменная является конечной, просто означает, что вы не можете направить ссылку куда-либо еще, но вы все равно можете изменить содержимое упомянутого объекта из любой функции.

Большая проблема, с которой вы столкнетесь, состоит в том, чтобы ждать, пока не будет вызван обратный вызов. Такой вид ожидания-ожидания может быть достаточно хорошим, но вы можете учитывать время ожидания, потоки и т. Д., В зависимости от того, чего вы пытаетесь достичь.

Кроме того, все это предполагает, что вы никогда не будете вызывать это дважды в соединении. В противном случае вам необходимо предоставить нам больше информации о вашей модели синхронизации.

Вот пример кода:

public int getUserid(String username) {
        final ValueBox<Integer> userid = new ValueBox<Integer>();

        connection.call("getUserid", new Responder() {
                public void onResult(final int result) {
                        System.out.println("userid: " + result);
                        userId.setValue(result);
                        //how to assign received value to userid and return it?
                }
        }, username);

        //wait for response
        while (userid.isEmpty()) {
                try{
                        Thread.sleep(100);
                } catch (Exception e) {}
        }

      return userid.getValue();
}
0 голосов
/ 28 мая 2009

Самое простое изменение - использовать что-то вроде java.util.concurrent.SynchronousQueue. Но, возможно, вы захотите предоставить управляемый событиями интерфейс самостоятельно.

...