ListView зависает, когда я нажимаю на элемент - PullRequest
0 голосов
/ 02 июля 2018

У меня есть функция selectWord(), которая заполняет две строки и ArrayList, затем она помещает их (строки) в ListView и TextView.

Что я хочу сделать, это когда кто-то нажимает на listItem, строки и ArrayList должны изменить свои значения и поместить новые значения в TextView и ListView.

Я создал функцию, которая выбирает слова из текстового файла, а затем показывает эти данные в представлениях, в ClickListener; я снова вызвал ту же функцию, чтобы она выбирала данные из текстового файла и помещала их в представления. ( приложение типа теста, выберите опцию и затем следующий вопрос )

Я написал похожий код пару дней назад, что работает.

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> words = new ArrayList<>();    //words list
    private ArrayList<String> defns = new ArrayList<>();    //deffinitions
    private String word;
    private String correct;
    public ArrayList<String> randOptions = new ArrayList<>();
    private Random randy = new Random();
    private TextView wordView;
    private ListView optionView;

    public void readFile() { //works fine
        //populate the ArrayLists
        String word, defn;
        Scanner file = new Scanner(getResources().openRawResource(raw.dictionary1));

        while(file.hasNextLine()) {
              String line = file.nextLine();
              String[] lineArray = line.split(" ");
              if (lineArray.length >= 2) {
                  word = lineArray[0];
                  defn = lineArray[1];
                  words.add(word);
                  defns.add(defn);
              }
          }
    }

    public void selectWord() {

        readFile(); //read file
        //get some data
        int rand = randy.nextInt(words.size());
        this.word = words.get(rand);
        this.correct = defns.get(rand);

        //make 4 diff options
        randOptions.add(correct);

        for(int i=0; i<3; i++) {
            rand = randy.nextInt(defns.size());
            if(randOptions.contains(defns.get(rand)))
                    i--;
            else
                randOptions.add(defns.get(rand));
        }
        Collections.shuffle(randOptions);

        //add the data to views
        wordView.setText(this.word);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, randOptions);
        optionView.setAdapter(adapter);
    }

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(layout.activity_main);

        wordView = findViewById(id.currentWord);
        optionView = findViewById(id.options);

        selectWord();

        optionView.setOnItemClickListener(
              new AdapterView.OnItemClickListener() {
                  @Override
                  public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                       String selected = ((TextView) view).getText().toString();
                       if (correct.equals(selected)) {
                           Toast.makeText(MainActivity.this, "Right", Toast.LENGTH_SHORT).show();
                       } else {
                              Toast.makeText(MainActivity.this, "Wrong", Toast.LENGTH_SHORT).show();
                       }
                       selectWord(); //so that it changes the vlaues in views but when I add that 
                       //line my hangs there soon as I click on the list item
               }
           }
       );    
}

1 Ответ

0 голосов
/ 02 июля 2018

optionView.setOnItemClickListener(...) использует AdapterView. Поэтому, когда вы вызываете selectWord(); из внутри этого ClickListener, оно зависает ... Почему? : просто потому, что вы воссоздаете ArrayAdapter<String> и снова устанавливаете его в ListView.

Вместо того, чтобы просить его убить себя (т.е. воссоздать себя с земли), вы можете попросить ArrayAdapter изменить свои данные, чтобы ListView все равно использовал тот же ArrayAdapter. В этом случае вы должны уведомить об изменениях, что-то вроде этого:

  1. Сначала удалите ArrayAdapter<String> adapter = .. и optionView.setAdapter из метода selectWord().
  2. Создайте global ArrayAdapter и установите его в ListView вне метода selectWord().
  3. Затем каждый раз, когда вы хотите изменить параметры .. и т. Д. selectWord().
  4. Затем очистите ArrayAdapter и снова заполните его.
  5. Наконец уведомить об изменениях.

// create this method to update the options (re-populate the ArrayAdapter)
// of course ArrayAdapter and randOptions should be GLOBAL
public void updateOptions() {
    adapter.clear(); 
    if (randOptions != null){
       for (String option : randOptions) {
           adapter.insert(option,adapter.getCount());
        }
    }     
    adapter.notifyDataSetChanged();
} 

// first declare the ArrayAdapter globally as a field
ArrayAdapter<String> adapter;

// inside onCreate() method, initialize the ArrayAdapter (i.e. outside the `selectWord()` method) 
// using this constructor: ArrayAdapter(Context context, int resource)
adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1);

// after that, set the adapter (it's empty by now)
optionView.setAdapter(adapter);

// fill the Random Options Array
selectWord();
// call update options
updateOptions();

// and use it inside the CLickListener like this
optionView.setOnItemClickListener(
          new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                // whatever ...
                selectWord(); //so that it changes the options in the array
                updateOptions(); // update options in the same ArrayAdapter
})});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...