1

I have an adapter class, I have a checkbox in this layout and with "OnClickListener" method I try to declare "check = true" but the ADT ask me declare a final the ViewHolder

This is my adapter class

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

}

how can i fix it?

TuGordoBello
  • 4,350
  • 9
  • 52
  • 78

4 Answers4

2

Because of the way the anonymous inner classes work, it would need to be final. Considering you seem to want to assign this same functionality to each and every row of your list, I believe what you should do is create a class that implements the OnClickListener interface, and holds a reference to the checkBox of which's state the functionality depends on. However, I'm sort of concerned about how many items you have, because if you had many items, this would cause a major memory problem.

So what I thought of just now is, try the following:

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

        }
    }
});

Because the anonymous class's onClick function is called with the parameter of the View that calls back upon it, therefore the View parameter in this case can only be the CheckBox. I think this is what you need.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
1

See this answer for a detailed description as to why variables referenced in an anonymous inner class must be final. However, in your case there's a simpler solution:

holder.checkBox1.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View checkBox) {
        if ((Checkable) checkBox).isChecked()) {
            // Do Stuff
        }
    }
}

Since the View parameter of OnClickListener is the actual View that was clicked, and you're setting this listener on the CheckBox, you can simply cast the View parameter to Checkable and reference it from there.

EDIT: Also, you might actually be looking for CheckBox.OnCheckedChangeListener rather than View.OnClickListener.

Community
  • 1
  • 1
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
0

Short answer - just copy ViewHolder into final variable and use it inside View.OnClickListener. Like this:

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

Longer answer - you need to make it final basically due to the way Java manages closures. You are actually creating an instance of anonymous inner subclass of OnClickListener here. Any variables which are used within that class have their values copied in via the autogenerated constructor. So here is another solution you could have - you can explicitly create OnClickListener subclass and pass ViewHolder reference to it.

Andrei Mankevich
  • 2,253
  • 16
  • 15
  • How can I use ``setChecked()`` inside OncliCk Method?? – TuGordoBello Jun 02 '14 at 19:53
  • Same way as `isChecked()` - `holderRef.checkBox1.setChecked(false);` – Andrei Mankevich Jun 02 '14 at 19:55
  • Doens't work ``if(holderRef.checkBox1.isChecked()){ holderRef.checkBox1.setChecked(false); }else{ holderRef.checkBox1.setChecked(true); }`` – TuGordoBello Jun 02 '14 at 20:11
  • 1
    What do you mean by "doesn't work"? :) It compiles, but what behaviour do you expect from it? Actually I don't see any sense in settings `OnClickListener` on check box and triggering its state. That's basic check box behavior after all. – Andrei Mankevich Jun 02 '14 at 20:16
  • I expressed wrong, it works but visually is not check. I only need check the checkbox when I clicked :D any idea? – TuGordoBello Jun 02 '14 at 20:24
  • But you don't need to do anything in order to make it checked when it is clicked, it is standard behaviour for check box. Just don't set `OnClickListener` and it will work this way :) If you need to know its state you should really use `CheckBox.OnCheckedChangeListener` for that. – Andrei Mankevich Jun 02 '14 at 20:27
0

If you put final in your holder object then it will place in the heap.

To reduce some memory going to the heap just use only the boolean from the holder as final instead the whole object.

example:

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 ){  

        }

    }
});
Rod_Algonquin
  • 26,074
  • 6
  • 52
  • 63
  • I don't think this is correct. This would "fix" the value of isChecked to the state it has when drawing the view, instead of getting the value when the checkbox is clicked. – matiash Jun 03 '14 at 02:02