Отображение доступных языков TTS в счетчике

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

Вот соответствующая часть кода:

package com.example.dshawn.ttsapp;

import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.*;

public class MainActivity extends AppCompatActivity implements

        AdapterView.OnItemSelectedListener {
    private TextToSpeech mTTS;
    Locale[] locales = Locale.getAvailableLocales();
    List<Locale> localeList = new ArrayList<Locale>();
    List<String> country=  new ArrayList<String>();
    List<String> asdf=  new ArrayList<String>();


    int sum=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int i) {
                if (i==TextToSpeech.SUCCESS){
                    for (Locale locale : locales) {
                        int res = mTTS.isLanguageAvailable(locale);
                        if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
                            sum++;
                            localeList.add(locale);
                            country.add(locale.getDisplayName());
                        }
                    }
                    asdf.add(Integer.toString(sum));


                }

            }
        });
        //Getting the instance of Spinner and applying OnItemSelectedListener on it

        Spinner spin = (Spinner) findViewById(R.id.spinner);
        spin.setOnItemSelectedListener(this);

        //Creating the ArrayAdapter instance having the country list
        ArrayAdapter<String> aa = new  ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,country);
        aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //Setting the ArrayAdapter data on the Spinner
        spin.setAdapter(aa);

    }

    //Performing action onItemSelected and onNothing selected
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
        Toast.makeText(getApplicationContext(),country.get(position) , Toast.LENGTH_LONG).show();
    }
    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        // TODO Auto-generated method stub
    }
}

После этой инициализации TTS я пытаюсь вывести сумму, она показывает 0. Я пытаюсь получить доступ к элементам в localeList и стране, выполняя что-то вроде String = country.get (1); и компилятор выдаст ошибку о том, что индекс, к которому я пытаюсь получить доступ, не существует и в списке 0 элементов. Итак, на данный момент кажется, что на устройстве, вероятно, нет доступных языков, но странно то, что когда я помещаю ArrayList страны в раскрывающееся меню счетчика через ArrayAdapter, фактические доступные страны на моем устройстве отображаются в счетчике меню, но оно сломано, вот гифка того, что я имею в виду:

Отображение доступных языков TTS в счетчике

Счетчик никогда не попадает в мой прослушиватель onItemSelected, и элемент не отображается в счетчике после щелчка по нему. Я вошел в настройки устройства, и те, которые появились, действительно являются доступными языками для TTS на этом устройстве. и когда я удаляю часть кода «if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE)», которая, похоже, никогда не будет доступна, в раскрывающемся меню счетчика ничего не будет. Таким образом, он явно каким-то образом захватывает доступные локали, но когда я пытался получить доступ к arraylist, он действовал так, как будто он был пуст, но каким-то образом он использует этот «пустой» Arraylist и получает правильные страны в поле счетчика, но блок счетчика сломан, предположительно, потому что ArrayList не работает, потому что я пробовал то же самое с ArrayList, который заполняю вручную, и элементы отображаются нормально, и я могу выбрать его в обычном режиме.

В чем может быть проблема? Я перепробовал все, что мог придумать, все, что я знаю, это проблема в части инициализации TTS.

В основном я не могу получить доступ ни к одному из элементов, которые были установлены или добавлены в методе onInit для TTS, что также приводит к поломке моего счетчика.

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

Nerdy Bunz 18.08.2018 10:50

Я добавил полный код, но не знаю, поможет ли это.

dshawn 19.08.2018 16:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
414
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Куда вы звоните String=country.get(1);? Поскольку это обратный вызов, вы не узнаете, когда он будет вызван. Если вы поместите код внутри onInit после блока операторов if, вы увидите значение?

Кажется, что я могу получить доступ к значениям в onInit, я снова попытался отобразить сумму, и она показывает 7 при доступе изнутри метода onInit. Но я не могу переместить свой счетчик в onInit, потому что мой ArrayAdapter не может быть применен внутри метода onInit. есть ли способ сохранить значения после onInit?

dshawn 16.08.2018 05:19

Да, сейчас было бы отличное время использовать Rx, создав поток и разместив значения в потоке, когда onInit завершится, а затем подписаться на onResume (не забудьте удалить в onPause или использовать Autodispose от Uber). Другой вариант - иметь класс слушателя и вызывать слушателя, который обновляет счетчик (слушатель может быть реализован действием, или вы можете спроектировать его так, чтобы он был более тестируемым с чистым классом java)

Zachary Sweigart 16.08.2018 05:23
Ответ принят как подходящий

Я думаю, проблема заключалась в том, что вы создавали адаптер (используя список стран) до того, как список был заполнен (потому что TTS еще не был инициализирован).

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

    private TextToSpeech mTTS;
    Locale[] locales = Locale.getAvailableLocales();
    List<Locale> localeList = new ArrayList<Locale>();
    List<String> country = new ArrayList<String>();

    // * - Move these two variables out here
    ArrayAdapter<String> aa;
    Spinner spin;

    int sum = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        Log.i("XXX", "onCreate() was called");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int i) {
                if (i == TextToSpeech.SUCCESS) {
                    // * - delay important tasks until TTS is initialized
                    startWhenTTSIsInitialized();
                }
            }
        });

        //Getting the instance of Spinner and applying OnItemSelectedListener on it
        spin = (Spinner) findViewById(R.id.spinner);

    }

    private void startWhenTTSIsInitialized() {

        Log.i("XXX", "startWhenTTSIsInitialized() was called");
        for (Locale locale : locales) {
            int res = mTTS.isLanguageAvailable(locale);
            if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
                sum++;
                localeList.add(locale);
                // * - 'country' is used to populate the adapter, so
                // this line must come first
                country.add(locale.getDisplayName());
            }
        }

        //Creating the ArrayAdapter instance having the country list
        // * - now it's safe to set the adapter because the country list has been populated
        aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, country);
        aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //Setting the ArrayAdapter data on the Spinner
        spin.setAdapter(aa);
        spin.setOnItemSelectedListener(this);

    }

    //Performing action onItemSelected and onNothing selected
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {

        Log.i("XXX", "onItemSelected() was called");
        Toast.makeText(getApplicationContext(), country.get(position), Toast.LENGTH_LONG).show();

    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {

        // TODO Auto-generated method stub

    }

}

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