Преобразовать асинхронную инициализацию TTS в синхронную

Мне нужно получить некоторую информацию из движка TTS, однако движок требует инициализации перед использованием. я знаю это TextToSpeech позвоню onInit уведомить, что сделано.

Я создал этот вспомогательный класс, чтобы превратить его в синхронный вызов:

public class PureTTSHelper implements TextToSpeech.OnInitListener {
    TextToSpeech tts;
    boolean ready;
    CompletableFuture<TextToSpeech> completableFuture;

    public PureTTSHelper(Context ctx){
        this.ready = false;
        this.tts = new TextToSpeech(ctx, this);
    }

    @Override
    public void onInit(int i) {
        ready = true;
        completableFuture.complete(tts);
    }

    public TextToSpeech getTTSSync(){
        if(ready){
            return tts;
        }

        completableFuture = new CompletableFuture<>();

        try {
            return completableFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        } catch (ExecutionException e) {
            e.printStackTrace();
            return null;
        }
    }
}
TextToSpeech tts = new PureTTSHelper(this).getTTSSync();

Это не работает Я считаю, что происходит то, что поток заблокирован return completableFuture.get() и никогда не получал шанс казнить completableFuture.complete(tts)Однако я не очень хорошо знаю, как работает параллелизм в Java, поэтому я не уверен, является ли это точной причиной.

Тем не менее, я абсолютно не знаю, как заставить это работать. Любые идеи приветствуются.


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

Кажется, что инициализация не так асинхронна, как я думал. Код

TextToSpeech tts = new PureTTSHelper(this).getTTSSync();

выполняется в деятельности onCreate и TextToSpeech объект не будет инициализирован до onCreate метод возвращает.

1 ответ

Моя первая реакция - решить эту проблему с помощью CountDownLatch инициализируется с подсчетом 1,

public class PureTTSHelper implements TextToSpeech.OnInitListener {
    TextToSpeech tts;
    CountDownLatch latch;

    public PureTTSHelper(Context ctx){
        this.latch = new CountDownLatch(1);
        this.tts = new TextToSpeech(ctx, this);
    }

    @Override
    public void onInit(int i) {
        latch.countDown();
    }

    public TextToSpeech getTTSSync(){
        try {
            latch.await();
            return tts;
        } catch (InterruptedException e) {
            // TODO
        }
    }
}

Я никогда не работал с TextToSpeech; надеюсь, я понял семантику правильной инициализации.

Другие вопросы по тегам