Доступ к переменным вне анонимного класса - PullRequest
0 голосов
/ 10 декабря 2018

В настоящее время я работаю со службами речи и текста IBM, включенными в Java Watson java SDK.Я пытаюсь установить транскрипт String равным транскрипту результатов.Однако, когда я запускаю этот код, значение не печатается.Я не уверен, почему это происходит, или как решить проблему.Любая помощь будет оценена.Я пытался использовать внешний сеттер со статической переменной вне основного метода, но мне это не удалось.

final String[] transcript = {""};
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
            }
        }
    });
    System.out.println(transcript[0]);

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Проблема в том, что recognizeUsingWebSocket - это асинхронный вызов.Таким образом, к тому времени, когда вы выполните System.out.println(transcript[0] вызов, который вы сделали службе IBM Watson, скорее всего, еще не завершен.

Вы будете знать, что асинхронная операция завершилась, когда метод обратного вызова onTranscriptionсрабатывает.Следовательно, внутри этого метода и после цикла for вы можете быть уверены, что в массиве transcript уже есть некоторые значения.Там вы можете делать с результатом все, что захотите.

Если вы хотите использовать значение стенограммы вне обратного вызова, самое простое решение - определить новый метод в вашем классе и вызвать его в концеобратного вызова onTranscript.

...
public void onTranscriptReceived(String[] transcript) {
     // Do whatever you want
}
...

final String[] transcript = {""};
service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
    @Override
    public void onTranscription(SpeechRecognitionResults speechResults) {
        for(int i = 0; i < speechResults.getResults().size(); i++){
            transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
        }
        onTranscriptReceived(transcript);
    }
});

Существует множество других решений для обработки асинхронных вызовов.Лично мне нравятся библиотеки ReactiveX , в вашем случае RxJava специально .На изучение может уйти какое-то время, но оно того стоит.

0 голосов
/ 10 декабря 2018

Вы можете заключить свой транскрипт массива в класс, который имеет свой собственный обработчик или приемник (способ обработки асинхронных запросов).

Примерно так:

import java.util.function.Consumer;

public class ArrayWrapper {

    private Consumer consumer;

    private Object [] array;

    public ArrayWrapper(int size) {
        this.array = new Object [size];
    }

    public void addConsumer(Consumer consumer) {
        this.consumer = consumer;
    }

    public void add(Object o, int index) {
        array[index] = o;
        consumer.accept(o);
    }

    public Object [] get() {
        return array;
    }
}

Тогда вы можетепросто реализуйте свою логику внутри Consumer:

ArrayWrapper transcript = new ArrayWrapper(1);
transcript.addConsumer(new Consumer() {
    @Override
    public void accept(Object o) {
        // perform your operations 
        System.out.println(o);
    }
});

service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
    @Override
    public void onTranscription(SpeechRecognitionResults speechResults) {
        for(int i = 0; i < speechResults.getResults().size(); i++){
            String newTranscript = transcript.get()[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
            transcript.add(newTranscript, 0);
        }
    }
});

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

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

Или вы можете сделать это более простым способом (без каких-либо дополнительных классов):

    final String[] transcript = {""};
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            //your operations
            System.out.println(s);
        }
    };
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
                consumer.accept(transcript[0]);
            }
        }
    });
}
...