4

I'm using a fragment to create a ListView filled with CheckBoxes. I tried my best to find the solution based on other questions but I can't seem to fix it. When I run the script without using the:

convertView.getTag();

My app runs fine but the positions of the Item s in the list don't save so. The view items jump around. However when I do use that method I get an error. The log cat states:

01-02 23:54:20.662: E/InputEventReceiver(1209): Exception dispatching input event.
01-02 23:54:20.672: D/AndroidRuntime(1209): Shutting down VM
01-02 23:54:20.672: W/dalvikvm(1209): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
01-02 23:54:20.782: E/AndroidRuntime(1209): FATAL EXCEPTION: main
01-02 23:54:20.782: E/AndroidRuntime(1209): java.lang.ClassCastException: com.MrBabilin.youdeserveadrink.Items cannot be cast to com.MrBabilin.youdeserveadrink.AlcoholList$MyCustomAdapter$ViewHolder
01-02 23:54:20.782: E/AndroidRuntime(1209):     at com.MrBabilin.youdeserveadrink.AlcoholList$MyCustomAdapter.getView(AlcoholList.java:169)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at android.widget.AbsListView.obtainView(AbsListView.java:2255)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at android.widget.ListView.makeAndAddView(ListView.java:1769)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at android.widget.ListView.fillDown(ListView.java:672)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at android.widget.ListView.fillGap(ListView.java:636)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5040)
01-02 23:54:20.782: E/AndroidRuntime(1209):     at 

This Activity consist of 3 classes. The main one: IngredientsActivity

public class IngredientsActivity extends FragmentActivity implements ActionBar.TabListener {

    private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.check_list);
        getActionBar().setTitle("Search");
        getActionBar().setIcon(R.drawable.search_1);

        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // For each of the sections in the app, add a tab to the action bar.
        actionBar.addTab(actionBar.newTab().setText("Alcahol").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setText("Juice").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setText("Other").setTabListener(this));
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {

        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        return true;
    }



    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {


        if (tab.getPosition() == 0) {
            AlcoholList simpleListFragment = new AlcoholList();
            getSupportFragmentManager().beginTransaction().replace(R.id.containert, simpleListFragment).commit();
        } 
        else if (tab.getPosition() == 1) {
            JuiceList androidlidt = new JuiceList();
            getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidlidt).commit();
        }



        else {

            OtherList androidversionlist = new OtherList();
            getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidversionlist).commit();

        }
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

       public static class DummySectionFragment extends Fragment {
        public DummySectionFragment() {
        }

        public static final String ARG_SECTION_NUMBER = "section_number";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            TextView textView = new TextView(getActivity());
            textView.setGravity(Gravity.CENTER);
            Bundle args = getArguments();
            textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
            return textView;
        }
    }



}

then the fragment : AlcoholList

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;

public class AlcoholList extends ListFragment{
    MyCustomAdapter dataAdapter = null;
    private  Set<String> recipesList = new HashSet<String>();
private ArrayList<Items> stateList  = new ArrayList<Items>();


public AlcoholList() {
          Items _states1 = new Items ("Gin",false);
          stateList.add(_states1);
Items _states2 = new Items ("Ginger Liqueur",false);
          stateList.add(_states2);
Items _states3 = new Items ("Citrus Vodka",false);
          stateList.add(_states3);
Items _states4 = new Items ("Champagne",false);
          stateList.add(_states4);
Items _states5 = new Items ("Coconut Rum",false);
          stateList.add(_states5);
Items _states6 = new Items ("Pear Vodka",false);
          stateList.add(_states6);
Items _states7 = new Items ("Rum",false);
          stateList.add(_states7);
Items _states8 = new Items ("Tequila",false);
          stateList.add(_states8);
Items _states9 = new Items ("Triple Sec",false);
          stateList.add(_states9);
Items _states10 = new Items ("Kahlua",false);
          stateList.add(_states10);
Items _states11 = new Items ("Vanilla Vodka",false);
          stateList.add(_states11);
Items _states12 = new Items ("Sake",false);
          stateList.add(_states12);
Items _states13 = new Items ("Bourbon",false);
          stateList.add(_states13);
Items _states14 = new Items ("Vodka",false);
          stateList.add(_states14);
Items _states15 = new Items ("Beer",false);
          stateList.add(_states15);


        };


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
          dataAdapter = new MyCustomAdapter(this.getActivity(),R.layout.da_item, stateList);
          setListAdapter(dataAdapter);
          SharedPreferences sharedPreferences = PreferenceManager
                    .getDefaultSharedPreferences(getActivity());
        recipesList = sharedPreferences.getStringSet("string",  recipesList);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.list_fragment, container, false);
    }


    @Override
    public void onListItemClick(ListView list, View v, int position, long id) {


    }

    private class MyCustomAdapter extends ArrayAdapter<Items>
    {

     private ArrayList<Items> stateList;
     public MyCustomAdapter(Context context, int textViewResourceId, 

             ArrayList<Items> stateList) 
             {
                   super(context, textViewResourceId, stateList);
                   this.stateList = new ArrayList<Items>();
                   this.stateList.addAll(stateList);
             }


     private class ViewHolder
      {

        CheckBox name;
      }
  @Override
     public View getView (int position, View convertView, ViewGroup parent) 
      {

              ViewHolder holder = null;

              Log.v("ConvertView", String.valueOf(position));

              if (convertView == null)
              {

                  LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

                 convertView = vi.inflate(R.layout.da_item, null);

                holder = new ViewHolder();
                convertView.setTag(holder);

                holder.name = (CheckBox) convertView.findViewById(R.id.ingredientbox);



                          holder.name.setOnClickListener( new View.OnClickListener() 
                          {
                                     public void onClick(View v)  
                                     {
                                       CheckBox cb = (CheckBox) v;
                                       Items _state = (Items) cb.getTag();
                                       _state.setSelected(cb.isChecked());
                                    }
                          });

              }
              else
              {

                  holder = (ViewHolder) convertView.getTag(); // THIS IS THE PROBLEM

              }

              Items state = stateList.get(position);


              holder.name.setText(state.getName());
              holder.name.setChecked(state.isSelected());

              holder.name.setTag(state);

              return convertView;
      }

    }
}

then the Array class : Items

public class Items {
String name ;
boolean selected;


public Items(String name, boolean selected){
    super();
    this.name=name;
    this.selected=selected;
}


public String getName() {
    return name;
}


public void setName(String name) {
    this.name = name;
}


public boolean isSelected() {
    return selected;
}


public void setSelected(boolean selected) {
    this.selected = selected;
}
}

I don't know if this is helpful but, this problem did not occur before I tried to implement fragment views. The code that worked was:

   public class IngredientsActivity extends Activity {
  MyCustomAdapter dataAdapter = null;

          @Override
          public void onCreate(Bundle savedInstanceState)
          {  
             super.onCreate(savedInstanceState);
             setContentView(R.layout.check_list);
             //Generate list View from ArrayList
              displayListView();
          }
                   private void displayListView()
          {

                  //Array list of countries
                  ArrayList<Items> stateList = new ArrayList<Items>();
                      Items _states2 = new Items ("420" ,false);

                      stateList.add(_states2);

                     Items _states3 = new Items ("Amanda Bynes" ,false);

                      stateList.add(_states3);

                     Items _states4 = new Items ("Angelina Jolie" ,false);

                      stateList.add(_states4);

                     Items _states5 = new Items ("Anne Hathaway" ,false);

                      stateList.add(_states5);

                     Items _states6 = new Items ("Bachelorette Contestants" ,false);

                      stateList.add(_states6);

                     Items _states7 = new Items ("Beauty and the Beast" ,false);

                      stateList.add(_states7);

                     Items _states8 = new Items ("Beyonce" ,false);

                      stateList.add(_states8);

                     Items _states9 = new Items ("Big Boi" ,false);

                      stateList.add(_states9);

                     Items _states10 = new Items ("Charlie Sheen" ,false);

                      stateList.add(_states10);

                  }
                  //create an ArrayAdaptar from the String Array
                  dataAdapter = new MyCustomAdapter(this,R.layout.da_item, stateList);
                  ListView listViews = (ListView) findViewById(R.id.ingList2);
                  // Assign adapter to ListView
                  listViews.setAdapter(dataAdapter);       
          }
private class MyCustomAdapter extends ArrayAdapter<Items>
{
 private ArrayList<Items> stateList;
public MyCustomAdapter(Context context, int textViewResourceId, 
ArrayList<Items> stateList) 
{
      super(context, textViewResourceId, stateList);
      this.stateList = new ArrayList<Items>();
      this.stateList.addAll(stateList);
}
  private class ViewHolder
  {
    CheckBox name;
  }




  @Override
 public View getView(int position, View convertView, ViewGroup parent) 
  {
          ViewHolder holder = null;
          Log.v("ConvertView", String.valueOf(position));
          if (convertView == null)
          {
             LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             convertView = vi.inflate(R.layout.da_item, null);
            holder = new ViewHolder();
            holder.name = (CheckBox) convertView.findViewById(R.id.ingredientbox);
            convertView.setTag(holder);
                      holder.name.setOnClickListener( new View.OnClickListener() 
                      {
                                 public void onClick(View v)  
                                 {
                                   CheckBox cb = (CheckBox) v;
                                   Items _state = (Items) cb.getTag();
                                   _state.setSelected(cb.isChecked());
                                }
                      });
          }
          else
          {
              holder = (ViewHolder) convertView.getTag();
          }
          Items state = stateList.get(position);
          holder.name.setText(state.getName());
          holder.name.setChecked(state.isSelected());
          holder.name.setTag(state);
          return convertView;
  }

}
}

The Question is : How can I prevent my application from crashing, when calling convertView.getTag()

user3155092
  • 95
  • 1
  • 2
  • 6
  • 1
    Write the line `convertView.setTag(holder);` after the `holder.name = (CheckBox) convertView.` line. As you are Directly setting the tag in your `getView` before the `Checkbox` initialization so it will set the null tag at that place. So set the Tag after `CheckBox` initialization. – GrIsHu Jan 03 '14 at 05:13
  • Same Problem: `01-03 00:24:35.272: E/AndroidRuntime(1341): java.lang.ClassCastException: com.MrBabilin.youdeserveadrink.Items cannot be cast to com.MrBabilin.youdeserveadrink.AlcoholList$MyCustomAdapter$ViewHolder` – user3155092 Jan 03 '14 at 05:25
  • I do not understand why you are again the setting the Tag as you have already set the Tag in your if condition. You are wrongly setting the tag to your Checkbox as your `Items` does not contain any integer value so you will not be able to set any integer tag to your view. – GrIsHu Jan 03 '14 at 05:27
  • What do you suggest for me to do? – user3155092 Jan 03 '14 at 06:24
  • Just comment that line and try out and check whether its working fine or not ? If any issue then tell me @user3155092 – GrIsHu Jan 03 '14 at 06:43

1 Answers1

6

R.layout.da_item file only contains R.id.ingredientbox so your covertView and holder.name are referring to the same object.

Now when you call

convertView.setTag(holder);

holder set to tag of convertView object and then you call

holder.name.setTag(state);

which overrides the tag as both objects are same.

Try to remove 2nd call and check.

EDIT Change your holder class to:

 private class ViewHolder
      {
        Items state;
        CheckBox name;
      }

don't write holder.name.setTag(state);. Instead do following:

holder.state=state;

Now when you want items just say:

Items _state = ((ViewHolder) cb.getTag()).state;
vipul mittal
  • 17,343
  • 3
  • 41
  • 44