我有一个适配器类,我在这个布局中有一个复选框,并使用"OnClickListener"方法,我试图声明"check = true",但ADT要求我声明一个final
ViewHolder
这是我的适配器类
public class MaterialAdapter extends ArrayAdapter<MaterialModel> {
public MaterialAdapter(Context context, int resource,
List<MaterialModel> objects) {
super(context, resource, objects);
// TODO Auto-generated constructor stub
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null; // IN THIS PART THE ADT ASK ME DECLARE FINAL
if(convertView == null){
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.material_adapter, parent, false);
holder = new ViewHolder();
holder.id_material = (TextView) convertView.findViewById(R.id.id_material);
holder.nombre_material = (TextView) convertView.findViewById(R.id.nombre_material);
holder.checkBox1 = (CheckBox) convertView.findViewById(R.id.checkBox1);
holder.checkBox1.setChecked(false);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
MaterialModel entry = getItem(position);
holder.id_material.setText(entry.getIdMaterial());
holder.nombre_material.setText(entry.getNombreMaterial());
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(holder.checkBox1.isChecked()){ // I CAN'T USE THIS BECAUSE IT'S NOT FINAL
}
}
});
return convertView;
}
public static class ViewHolder{
private TextView id_material;
private TextView nombre_material;
private CheckBox checkBox1;
}
}
我该如何修复它?
由于匿名内部类的工作方式,它需要是final。考虑到你似乎想要分配相同的功能,你的列表的每一行,我认为你应该做的是创建一个类实现OnClickListener接口,并持有一个引用的checkBox的状态的功能所依赖的。然而,我有点担心你有多少项,因为如果你有很多项,这将导致一个主要的内存问题。
所以我刚才想到的是,试试下面的方法:
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
CheckBox checkBox = (CheckBox) v;
if(checkBox.isChecked()){ // I CAN USE THIS
}
}
});
因为匿名类的onClick函数是用回调它的View的参数来调用的,所以在这种情况下View参数只能是CheckBox。我想这就是你需要的。
关于为什么在匿名内部类中引用的变量必须是final的详细描述,请参阅此回答。但是,在您的情况下,有一个更简单的解决方案:
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View checkBox) {
if ((Checkable) checkBox).isChecked()) {
// Do Stuff
}
}
}
由于OnClickListener
的View
参数是被点击的实际视图,并且您将此侦听器设置在CheckBox
上,因此您可以简单地将View
参数强制转换为Checkable
并从那里引用它。
编辑:此外,您实际上可能正在寻找CheckBox.OnCheckedChangeListener
而不是View.OnClickListener
。
如果你把final
放在你的holder
对象中,那么它将被放置在堆中。
为了减少堆上的内存,只使用来自holder的布尔值作为final,而不是整个对象。
例子:
holder.nombre_material.setText(entry.getNombreMaterial());
final boolean isChecked = holder.checkBox1.isChecked();
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isChecked ){
}
}
});
简短的回答-只需将ViewHolder
复制到final
变量中并在View.OnClickListener
中使用它。这样的:
final ViewHolder holderRef = holder;
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(holderRef.checkBox1.isChecked()){
}
}
});
更长的答案-你需要使它最终基本上由于Java管理闭包的方式。您实际上是在这里创建OnClickListener
的匿名内部子类的实例。在该类中使用的任何变量的值都通过自动生成的构造函数复制进来。所以这里是另一个解决方案,你可以有-你可以显式地创建OnClickListener
子类,并传递ViewHolder
引用给它。