Передача значения переменной не ссылки в OnClickListener () - PullRequest
0 голосов
/ 09 января 2010

Я пытаюсь настроить большое количество OnClickListeners через цикл for. Каждое представление должно запускать метод при нажатии; представление 0 должно запускать метод со значением 0, представление 1 со значением 1 и т. д.

Однако, если я объявляю OnClickListener с помощью переменной, которая увеличивается через циклы for, OnClickListener запоминает ссылку на переменную, а не на значение переменной во время ее объявления.

Это, вероятно, не очень понятно - вот код:

for (int i = 0; i < 20; i++) {
    cells[i] = (ImageView) findViewById(cellIDs[i]);
    cells[cellnumber++].setOnClickListener(new OnClickListener() {
    public void onClick(View v){
          cellClicked(cellnumber, v);
       }
    });
}

Это правильно настраивает OnClickListeners для каждой ячейки, но в зависимости от того, какая из них нажата, она всегда выполняет вызовы cellClicked со значением 21.

Я знаю, что могу вручную настроить OnClickListeners, используя cell[0]. , , cellClicked(0, v), но есть ли способ сделать это так, чтобы ClickListener передавал значение переменной, а не ссылку на переменную в цикле for?

(Я видел несколько страниц, на которых говорилось, что Java обычно работает с передачей значений, а не ссылок, но я предполагаю, что библиотеки Android каким-то образом делают это по-другому, и, следовательно, мои трудности здесь.)

Ответы [ 2 ]

6 голосов
/ 09 января 2010

Нет ничего "особенного" в семантике Java в Android.

cellClicked на самом деле не вызывается при создании каждого слушателя, а cellnumber не является локальным для анонимного класса, который вы создаете каждый раз, поэтому каждый слушатель ссылается на одну и ту же переменную и, таким образом, получает одно и то же значение.

Используйте метод View.setTag(), чтобы прикрепить идентификатор ячейки к каждому View. Тогда вам нужен только один экземпляр слушателя, который в своем методе onClick вызывает v.getTag(), чтобы получить идентификатор ячейки.

Edit:
Вот некоторый полностью непроверенный код. На самом деле, я не знаю, насколько вы можете использовать целое число в штучной упаковке. Во всяком случае, это начало:

OnClickListener listener = new OnClickListener() {
    public void onClick(View v) {
        int cellId = (int) v.getTag();
        cellClicked(cellId, v);
    }
}

View v;
for (int i = 0; i < 20; i++) {
    v = findViewById(cellIDs[i]);
    v.setOnClickListener(listener);
    v.setTag(i);
}
0 голосов
/ 09 января 2010

Ваш OnClickListener не хранит никаких состояний, поэтому вы всегда получаете одно и то же значение cellnumber. Возможно, вы захотите создать собственное расширение OnClickListener, которое будет принимать cellnumber через конструктор и сохранять его как переменную-член для дальнейшего использования. Таким образом, каждый слушатель будет иметь различную копию значения cellnumber, а не все ссылки на тот же.

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