【问题标题】:Passing a variable's value not reference in an OnClickListener()在 OnClickListener() 中传递变量的值而不是引用
【发布时间】:2010-01-09 00:51:34
【问题描述】:

我正在尝试通过 for 循环设置大量 OnClickListener。每个视图在点击时都应该运行一个方法; view 0 应该运行值为 0 的方法,view 1 应该运行值为 1 的方法,等等。

但是,如果我使用通过 for 循环递增的变量来声明 OnClickListener,则 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,但无论单击哪个单元格,它总是运行值为 21 的 cellClicked 调用。

我知道我可以使用 cell[0] 手动设置 OnClickListeners。 . . cellClicked(0, v), 但是有没有办法让 ClickListener 传递变量的值而不是 for 循环中对变量的引用?

(我看到一些页面说 Java 通常通过传递值而不是引用来运行,但我认为 Android 库以某种方式做不同的事情,因此我在这里遇到了困难。)

【问题讨论】:

    标签: java android


    【解决方案1】:

    Android 中的 Java 语义没有什么“特别”之处。

    cellClicked 在您创建每个侦听器时实际上并没有被调用,cellnumber 不是您每次创建的匿名类的本地,因此每个侦听器都引用相同的变量,因此得到相同的价值。

    使用View.setTag() 方法将单元ID 附加到每个View。那么您只需要一个监听器实例,它在其onClick 方法中调用v.getTag() 来获取单元ID。

    编辑:
    这是一些完全未经测试的代码。我真的不知道你是否可以像这样投射一个盒装整数。无论如何,这是一个开始:

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

    【讨论】:

    • 谢谢,这很有帮助。我会尝试一下,看看我能得到什么。
    • 太棒了,这正是我所需要的。由于您不能直接从对象转换为 int,因此需要花费一些时间,但最终我发现可以这样做:“int cellID = Integer.valueOf(v.getTag().toString());” .可能有一种更直接的方法,但它奏效了!再次感谢。
    • 既然已经有了 id 为什么还需要标签?只需在侦听器中使用 v.getId() 即可。
    • 单元 ID (0-19) 与视图的资源 ID 是分开的。
    • 那么“int cellId = (int) v.getTag()”和“int cellId = (Integer) v.getTag()”有什么区别?前者会引发有关无效类型转换的错误,而后者则可以正常工作。 (Integer) 是否使它对数据执行一些解释,而 (int) 试图将数据严格保存为 int?如果答案有点冗长,请不要打扰 - 你已经帮了很多忙了!
    【解决方案2】:

    您的 OnClickListener 未存储任何状态,因此您始终获得相同的 cellnumber 值。您可能希望创建一个自定义 OnClickListener 扩展,该扩展通过构造函数获取 cellnumber 并将其存储为成员变量以供以后使用,这样每个侦听器将拥有 cellnumber 值的不同副本,而不是全部引用一样的。

    【讨论】:

      猜你喜欢
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 2011-02-03
      相关资源
      最近更新 更多