I have a selectWord()
function that populates two strings and an ArrayList
, then it puts them(strings) into ListView
and TextView
.
What I want to do is when someone clicks on the listItem
, the strings and ArrayList
should change their values and put new values in TextView
and ListView
.
I created a function that selects words from text file and then shows that data into views, in ClickListener
; what I did is call to the same function again so that it selects data from text file and put it into the views. (a quiz type app, select an option and then next question)
I wrote similar code couple of days ago that work.
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(...)
uses AdapterView
. So when you call selectWord();
from inside this ClickListener
it hangs... Why?: Simply because you are re-creating the ArrayAdapter<String>
and setting it again in the ListView
.
Instead of asking it to kill itself (i.e. recreate itself from ground), you can ask the ArrayAdapter
to change its data so the ListView
will still use the same ArrayAdapter
. In this case, you should notify the changes, something like this:
ArrayAdapter<String> adapter = ..
and optionView.setAdapter
from selectWord()
method.ArrayAdapter
and set it in the ListView
outside the selectWord()
method.selectWord()
.ArrayAdapter
and repopulate it again.// 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
})});