单击项目时 ListView 挂起

ListView hangs when i click on an Item

我有一个 selectWord() 函数来填充两个字符串和一个 ArrayList,然后它将它们(字符串)放入 ListViewTextView.

我想要做的是,当有人点击 listItem 时,字符串和 ArrayList 应该更改它们的值并将新值放入 TextViewListView .

我创建了一个函数,可以从文本文件中提取 selects 个单词,然后在 ClickListener 中将数据显示到视图中;我所做的是再次调用相同的函数,以便它 selects 来自文本文件的数据并将其放入视图中。 (一个测验类型的应用程序,select一个选项,然后是下一个问题

几天前我写了类似的代码。

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
               }
           }
       );    
}

optionView.setOnItemClickListener(...) 使用 AdapterView。所以当你从 inside 调用 selectWord(); 这个 ClickListener 它挂起...... 为什么?: 仅仅因为你是-创建 ArrayAdapter<String> 并在 ListView.

中再次设置它

与其要求它自杀(即从地面重新创建自己),您可以要求 ArrayAdapter 更改其数据,这样 ListView 仍将使用相同的 ArrayAdapter .在这种情况下,您应该通知更改,如下所示:

  1. 首先从 selectWord() 方法中删除 ArrayAdapter<String> adapter = ..optionView.setAdapter
  2. 创建global ArrayAdapter并在selectWord()方法外的ListView中设置。
  3. 然后每次你想改变选项..etc调用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
})});