2010-01-09 3 views
0

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

Однако, если я объявляю 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 библиотеку как-то сделать по-другому, и, следовательно, мои трудности здесь.)

ответ

6

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

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

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

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

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

Спасибо, это очень полезно. Я немного экспериментирую и понимаю, что я могу получить. –

+0

Удивительно, это было то, что мне нужно. Потребовалось немного возиться, так как вы не можете напрямую использовать объект от int, но в итоге я решил, что это сделает: «int cellID = Integer.valueOf (v.getTag(). ToString()); , Там может быть более прямой способ сделать это, но это сработало! Еще раз спасибо. –

+1

Веселый хорошо. 'int cellId = (Integer) v.getTag()' должен работать. –

0

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

Смежные вопросы