вернуть строку из обратного вызова - Java - PullRequest
8 голосов
/ 27 июля 2011

Кто-нибудь знает, как я могу решить следующую проблему. Я хочу вернуть строку из обратного вызова, но я получаю только «Конечная локальная переменная s не может быть назначена, так как она определена в типе включения», из-за final.

 public String getConstraint(int indexFdg) {
    final String s;
    AsyncCallback<String> callback = new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {
            caught.printStackTrace();
        }

        public void onSuccess(String result) {
            s = result;
        }
    };
    SpeicherService.Util.getInstance().getConstraint(indexFdg, callback);
    return s;
    }

Ответы [ 2 ]

15 голосов
/ 27 июля 2011

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

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

В качестве простого (неполного) примера вам необходимо изменить это:

 String s = getConstraint();
 someGuiLabel.setText(s);

На что-то вроде этого:

 myCallback = new AsyncCallback<String>() {
     public void onSuccess(String result) {
         someGuiLabel.setText(result);
     }
 }
 fetchConstraintAsynchronously(myCallback);

Редактировать

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

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

В Java есть такой класс (Future<V>), который широко используется ExecutorService API .

4 голосов
/ 09 октября 2017

Альтернативный обходной путь - определить новый класс с именем SyncResult

public class SyncResult {
    private static final long TIMEOUT = 20000L;
    private String result;

    public String getResult() {
        long startTimeMillis = System.currentTimeMillis();
        while (result == null && System.currentTimeMillis() - startTimeMillis < TIMEOUT) {
            synchronized (this) {
                try {
                    wait(TIMEOUT);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        synchronized (this) {
            notify();
        }
    }
}

Затем измените свой код на

public String getConstraint(int indexFdg) {
    final SyncResult syncResult = new SyncResult();
    AsyncCallback<String> callback = new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {
            caught.printStackTrace();
        }

        public void onSuccess(String result) {
            syncResult.setResult(result);
        }
    };
    SpeicherService.Util.getInstance().getConstraint(indexFdg, callback);
    return syncResult.getResult();
}

Метод getResult() будет заблокирован до тех пор, пока не будет вызван метод setResult(String) или пока не будет достигнут TIMEOUT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...