我有一个适配器类,我在这个布局中有一个复选框,并使用" 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;
}
}
我该如何解决?
答案 0 :(得分:2)
由于匿名内部类的工作方式,它需要是最终的。考虑到您似乎想要将相同的功能分配给列表的每一行,我相信您应该做的是创建一个实现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
}
}
});
因为使用View的参数调用匿名类的onClick函数,因此在这种情况下View参数只能是CheckBox。我认为这就是你所需要的。
答案 1 :(得分:1)
有关匿名内部类中引用的变量必须为final的原因的详细说明,请参阅this answer。但是,在您的情况下,有一个更简单的解决方案:
holder.checkBox1.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View checkBox) {
if ((Checkable) checkBox).isChecked()) {
// Do Stuff
}
}
}
由于View
的{{1}}参数是点击的实际视图,并且您在OnClickListener
上设置了此侦听器,因此您只需转换CheckBox
参数View
并从那里引用它。
编辑:此外,您实际上可能正在寻找Checkable
而不是CheckBox.OnCheckedChangeListener
。
答案 2 :(得分:0)
简短回答 - 只需将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
引用传递给它。
答案 3 :(得分:0)
如果您将final
放在holder
对象中,那么它将放在堆中。
为了减少一些进入堆的内存,只需使用holder中的boolean作为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 ){
}
}
});