Results 1 to 10 of 10
  1. #1
    sehudson's Avatar
    sehudson is offline Senior Member
    Join Date
    Mar 2010
    Posts
    356
    Rep Power
    5

    Default OnClick inside a loop

    I am doing some Android programming, and I had a question about onClickListeners (android is done in Java).


    I am dynamically creating table rows as I walk down Cursor results of an SQL query and adding them to the table. Right before I add the table to the row, I am trying to set a listener for EACH row, and the action will be based on the row. The problem is that when the action is triggered, 'rowCount' keeps evaluating to the total # of Rows, instead of what it was at the time I created the Listener. Any way to get this to work?

    Java Code:
    while(values.moveToNext()){
        	 System.out.println("On Row "+RowCount);
        	 trA[RowCount] = new TableRow(this);             
    
                  trA[RowCount].setId(RowCount);
                  
                  
                  trA[RowCount].setOnClickListener(
                          new OnClickListener() {
                              @Override
                              public void onClick(View v) {
                            	 // SetValues(trA[RowCount].getId());
                              
                              }
                              
    
                  });
    
                  //Add the Row to the table
                  tl.addView(trA[RowCount]);
                  RowCount++;
         }

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,317
    Rep Power
    25

    Default

    'rowCount' keeps evaluating to the total # of Rows, instead of what it was at the time I created the Listener
    Sounds like you're not reseting the value. What shows when the println is printed on entry to the loop?

  3. #3
    sehudson's Avatar
    sehudson is offline Senior Member
    Join Date
    Mar 2010
    Posts
    356
    Rep Power
    5

    Default

    I switched it around a little bit. I set currentRow to-1 right before the loop, and do the increment as soon as I enter the loop. There are 6 rows in the table(cursor results) so I get

    On Row 0
    On Row 1
    On Row 2
    On Row 3
    On Row 4
    On Row 5

    I think the issue is the listener. I guess when the code reaches the setOnClickListener, it doesn't actually do anything, other than recognize that a listener is created? So after the table is created, I click on a row, and the listener is activated, but the code inside the listener references 'currentRow', but I was hoping that the 'currentRow' it used was the 'currentRow' at the time I 'declare' the listener, but apparently not because when I click the row, the currentRow value it uses is 5, no matter which row I click on.

    So it looks like this

    Java Code:
    currentRow=-1;
    while(values.moveToNext()){
    currentRow++;
        	 System.out.println("On Row "+currentRow);
        	 trA[currentRow] = new TableRow(this);             
    
                  trA[currentRow].setId(currentRow);
                  
                  
                  trA[currentRow].setOnClickListener(
                          new OnClickListener() {
                              @Override
                              public void onClick(View v) {
                            	 // SetValues(trA[currentRow].getId());
                              
                              }
                              
    
                  });
    
                  //Add the Row to the table
                  tl.addView(trA[currentRow]);
         }
    Last edited by sehudson; 05-26-2011 at 03:24 AM.

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,317
    Rep Power
    25

    Default

    at the time I 'declare' the listener
    Do you mean at the time you create an instance of the listener?
    You could pass the current value of the variable to the listener when you create the listener.

    Or when you add the listener to the component that has the actions listened for?
    Add a method to the listener to call to pass the value of the variable at that time.

  5. #5
    sehudson's Avatar
    sehudson is offline Senior Member
    Join Date
    Mar 2010
    Posts
    356
    Rep Power
    5

    Default

    I think I see what you are saying, you mean in the 'guts' of the listener?

    This portion,

    Java Code:
                  trA[currentRow].setOnClickListener(
                          new OnClickListener() {
                              @Override
                              public void onClick(View v) {
                            	//logic here?????
                              
                              }
                              
    
                  });

    I don't think that part gets evaluated until the event actually occurs.

  6. #6
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,317
    Rep Power
    25

    Default

    I gave two options, which are you referring to?

    I don't think that part gets evaluated until the event actually occurs.
    Instead of using an anonymous class, create one that you can pass args to its constructor

    Or perhaps you could add a line in what your have: ???
    Java Code:
     trA[currentRow].setOnClickListener(
                          new OnClickListener() {
                               final int SavedRowCnt = currentRow;  // Save current value
                              @Override
                              public void onClick(View v) {
                            	//logic here?????
                              
                              }
                              
    
                  });

  7. #7
    sehudson's Avatar
    sehudson is offline Senior Member
    Join Date
    Mar 2010
    Posts
    356
    Rep Power
    5

    Default

    can you show an example of your 1st suggestion, I'm not sure what you mean.

    "Instead of using an anonymous class, create one that you can pass args to its constructor"

  8. #8
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,317
    Rep Power
    25

    Default

    I meant to say: define a new class that is a listener with a constructor that you can pass the values to the object.
    Something like:
    Java Code:
    class MyListener extends listener {
      MyListener(int valueToSave) {
        this.valueToSave = valueToSave;  // save value locally

  9. #9
    sehudson's Avatar
    sehudson is offline Senior Member
    Join Date
    Mar 2010
    Posts
    356
    Rep Power
    5

    Default

    I created a class called MyListener

    Java Code:
    public class MyListener implements OnClickListener {
    	private int rowID;
    
    	public MyListener(int valueToSave) {
    	    this.rowID = valueToSave;  // save value locally	    
    	    
    	    System.out.println("*** Row"+valueToSave);
    	    
    	  }
    
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		
    	}
    
    
    }
    As I create each row, I am setting up each of the Listeners in my MyClickListener[]:

    ocl[rowCount] = new MyListener(rowCount)

    I have a print out, so I see that the listener is being created, but for some reason, this guy isn't being triggered when I click on a row.
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub

    }
    Last edited by sehudson; 05-29-2011 at 05:01 AM.

  10. #10
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    but for some reason, this guy isn't being triggered when I click on a row.
    Are you calling setOnClickListener() on the view to associate the listener with it?

    ------------

    As you have seen the value the listener gets is the value you give it when you create it. Using a global variable for the row count is asking for trouble: use a local one passed to the listener's constructor or just made final as in the following Swing example:

    Java Code:
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    
    public class ListenerEg extends JPanel {
    	private static final int NUM = 10;
    		// better not to have a variable row...
    	private int row;
    	
    	public ListenerEg() {
    		super(new GridLayout(0, 1));
    		for(row = 0; row < NUM; row++) {
    			JButton toAdd = new JButton("Click me!");
    			final int num = row;
    			toAdd.addActionListener(new ActionListener() {
    				@Override
    				public void actionPerformed(ActionEvent arg0) {
    					System.out.println("Click! num=" + num + " row=" + row);
    				}
    			});
    			add(toAdd);
    		}
    	}
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			@Override
    			public void run() {
    				JFrame frame = new JFrame("ListenerEg test");
    				frame.add(new ListenerEg());
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    				frame.pack();
    				frame.setVisible(true);
    			}
    		});
    	}
    }

Similar Threads

  1. Help with while loop inside a switch case
    By Shesaid in forum New To Java
    Replies: 2
    Last Post: 04-01-2011, 03:36 AM
  2. if else inside while loop??
    By jonytek in forum New To Java
    Replies: 3
    Last Post: 02-17-2011, 09:28 AM
  3. Loop inside a switch
    By mustachMan in forum New To Java
    Replies: 3
    Last Post: 02-26-2010, 03:25 AM
  4. Problem printing inside FOR loop
    By cassysumandak in forum New To Java
    Replies: 1
    Last Post: 10-04-2009, 05:02 PM
  5. println doesn't print from inside for loop, et.al.
    By rdtindsm in forum New To Java
    Replies: 5
    Last Post: 03-27-2009, 01:19 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •