views:

54

answers:

2

I want to add separate event listener to dynamically created list of textview. The code so far is like this:

while (cur.moveToNext()){
    TextView tv = new TextView(this);
    temp = cur.getString(cur.getColumnIndexOrThrow("_ID"));
    result = "some text";
    tv.setText(result);
    tv.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent myIntent = new Intent(v.getContext(), newsDetails.class);
                myIntent.putExtra("id", temp);
                startActivity(myIntent);
            }
        });
    lOut.addView(tv);
}

But this does not work. Separate text views are created in a form of list but separate event listeners are not working.

A: 

The problem is probably your temp variable. I'm assuming it is a member variable? The code within the event listener will use the value of temp when the event is triggered, not the value that it was when the onClick() function was defined.

Off the top of my head, the easiest solution I can think of is to store the temp object as the TextView's tag, and then retrieve it within the onClick() function.

while (cur.moveToNext()){
        TextView tv = new TextView(this);
        temp = cur.getString(cur.getColumnIndexOrThrow("_ID"));
        result = "some text";
        tv.setText(result);
        tv.setTag(temp);
        tv.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    Intent myIntent = new Intent(v.getContext(), newsDetails.class);
                    myIntent.putExtra("id", v.getTag());
                    startActivity(myIntent);
                }
            });
        lOut.addView(tv);
    }
Aaron C
+2  A: 

Assuming that this is actual code rather than pseudo-code, then I agree with Aaron on the fact that use of member fields is the probable source of your problem. I disagree with the solution, however: you should not be using fields. (If you have to name your field "temp", this is a pretty good hint that it should be a local instead.) If you create a "final" local variable, then you know it won't change out from under you, and that fixed value will be locked into your anonymous subclass (i.e. the listener).

The code becomes the following:

while (cur.moveToNext()){
    TextView tv = new TextView(this);
    final String temp = cur.getString(cur.getColumnIndexOrThrow("_ID"));
    final String result = "some text";
    tv.setText(result);
    tv.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent myIntent = new Intent(v.getContext(), newsDetails.class);
                myIntent.putExtra("id", temp);
                startActivity(myIntent);
            }
        });
    lOut.addView(tv);
}

You would, of course, want to get rid of the fields named "temp" and "result", since the local variables take their place.

beekeeper
Yeah, this approach is definitely better. That's what I get for trying to answer technical questions on Sunday morning :) My approach might actually have the same problem as before since you would be storing a pointer to the same member variable anyway.
Aaron C