2009-05-28 3 views
6

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

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

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

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

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

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

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

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

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

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

Спасибо. Его нужно вызывать более одного раза, хотя ... Какую модель синхронизации вы имеете в виду, чтобы читать/писать с этого объекта ValueBox? Это будет довольно сложно ... – serg

+0

Проблема в том, что вы могли бы иметь несколько вызовов getUserId, прежде чем вы когда-нибудь сможете обработать userId (например, представьте, что у вас было 5 вызовов в первые 100 мс). Тогда у вас возникнет риск перезаписи вещей и т. Д. Что вы хотите делать в таких ситуациях? – Uri

+0

Наверное, не обрабатывайте дальнейшие запросы до тех пор, пока не будет выполнен текущий. – serg

0

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