1

I am making an app that uses listview and listadapters. It worked fine but I found a memoryleak in the getgroupview-method. Before I inflated an xml-file everytime and that caused a leak.

 groupRow = inflater.inflate(R.layout.activity_phrase, parent, false);

In other words - i did not use the convertview. So I changed the syntax to:

if (convertView == null) {
          groupRow = inflater.inflate(R.layout.activity_phrase, parent, false);
}
else {
     groupRow = convertView;
} 

After this change I got problems with the checkboxitems. if I click on a checkbox and scrolldown and up more and more boxes are checked. Here I show an image of the list when I only checked ONE item and have scrolled up and down for a whilelistview

And here is all code in the overridden method getChildView

 public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
     //LayoutInflater inflater = (LayoutInflater) weakContext.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     //WeakReference <LayoutInflater> inflaterW = new WeakReference <LayoutInflater> (inflater);

     if (convertView == null) {
         LayoutInflater inflater = (LayoutInflater) weakContext.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     }
     else {
         groupRow = convertView;
     } 
     final View theRow = groupRow;

     final int group_Position = groupPosition;

     TextView textView;
     if (isExpanded) {
         textView = (TextView) theRow.findViewById(R.id.groupTitle); // fetstil för grupptitel om expanderad
         textView.setTypeface(null, Typeface.BOLD);
         textView.setText(titles[groupPosition]);
     }
     else {
         textView = (TextView) theRow.findViewById(R.id.groupTitle);
         textView.setText(titles[groupPosition]);
         textView.setTypeface(null, Typeface.ITALIC);
     }

     System.out.println("grupppos: " + groupPosition);
     System.out.println("size checked list: " + checked.size());
     CheckBox cb = (CheckBox) theRow.findViewById(R.id.check);
     for (int i = 0; i < checked.size(); i++) {   // kontrollera om aktuell grupp som visas i vyn är tillagd i favoriter. 
         if (checked.get(i) == groupPosition) {
             cb.setChecked(true);
             System.out.println("TRUE");
         }
         else {

         }
     }


     // Lyssnare till checkboxobjektet. 
     cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
             if (isChecked) { // Tillagd i favoriter
                 checked.add(group_Position); // registrera att denna position är tillagd som favorit
                    System.out.println("I SETONCHECKEDCHANGELISTENER"); 
                 // Lägger in nödvändiga parametrar i mysqlLite.
                 int n_childs = contents[group_Position].length;

                 switch(n_childs) { // om båda könen
                    case 1: sql.addPhrase(group_Position, category, titles[group_Position], contents[group_Position][0], 
                             sound[group_Position][0]);
                        break;
                    case 2:  sql.addPhrases(group_Position, category, titles[group_Position], contents[group_Position][0], // om kap o ka
                             contents[group_Position][1], sound[group_Position][0], sound[group_Position][1]);
                        break;
                 }
             }
             else { // avregistrerad från favoriter
                 for (int i = 0; i < checked.size(); i++) {
                     if (checked.get(i) == group_Position) {
                         checked.remove(i); 
                     }
                 }

                int n_phrases = sql.getRowCount();
                Object[][] phrase = sql.getPhraseList();
                int id = -1;
                for (int i = 0; i < n_phrases; i++) {
                    if ((Integer) phrase[i][1] == group_Position && (Integer) phrase[i][2] == category) {
                        id = (Integer) phrase[i][0];
                    }
                }
                sql.deletePhrase(id); // radera fras från mysqlLite m.a.p. primärnyckel-id.     
            }

          }
          });

     return theRow;
 }

Greatful for help!!!!!

Björn Hallström
  • 3,775
  • 9
  • 39
  • 50

1 Answers1

1

You call cb.setChecked(true), you should also call cb.setChecked(false) in the corresponding else branch. Since the views are recycled, also the view state is recycled and you will have to reset it yourself.

Also, there does not seem to be any code where you inflate the view in the first place (if convertView is null) but that's likely just an issue with this question.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • I should have mentioned that I put cb.setChecked(false) in the else-bransch before without success. What happens is the opposite - a checked Item is unchecked if its scrolled out of view and then come back. – Björn Hallström Jun 25 '13 at 14:57
  • I looked att Vogellas example of listviews. Maybe I should implement that instead - for instance put the listener in the if-bransch which is activated when convertview is null – Björn Hallström Jun 25 '13 at 16:42
  • @user2365568 The for loop around it makes things a little more complicated. By default the checkbox should be unchecked and if the for loop finds a match, then set it to checked. – laalto Jun 25 '13 at 18:31
  • I made I few changes. Now the sqlitedatabase that stores the data is also distorted. The strange thing is that when scrolling, the listener (setOnCheckedChangeListener) reacts to that, not only when a checkbox is checked. I just cant get it - why the listener now and then listens to scrolling. When it listens - it means data is added to mysqlite. Maybe I should take a rest after 14 hours . :-) – Björn Hallström Jun 25 '13 at 19:11