-1

Below is my Adapter class where i am retreving phone contacts, trying to get multi selection of contacts using check boxes.

 public ProfileAdapter(Activity activity, int textViewResourceId, List<Profile> listCont,int renderer, String profileType) {
        super(activity, textViewResourceId, listCont);
        this.renderer = renderer;
        this.listCont = listCont;
        this.activity = activity;
        this.profileType=profileType;

        checkBoxState=new boolean[listCont.size()];
    }

    private class ViewHolder
    {
      ImageView photo;
      TextView text,textContNo, textEmailId;
      CheckBox checkBox;
    }

    @TargetApi(9)
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

         View view = convertView;

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) (getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE));
            view = inflater.inflate(renderer, null);
             viewHolder=new ViewHolder();

             //cache the views
                viewHolder.photo=(ImageView) view.findViewById(R.id.photo);
                viewHolder.text=(TextView) view.findViewById(R.id.name);
                viewHolder.textContNo=(TextView) view.findViewById(R.id.contactno);
                viewHolder.textEmailId=(TextView) view.findViewById(R.id.emailId);
                viewHolder.checkBox=(CheckBox) view.findViewById(R.id.checkBox1);

                viewHolder.checkBox
                  .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                        Profile element = (Profile) viewHolder.checkBox
                          .getTag();
                      element.setSelected(buttonView.isChecked());

                    }
                  });
              view.setTag(viewHolder);
              viewHolder.checkBox.setTag(listCont.get(position));
            } else {
              view = convertView;
              ((ViewHolder) view.getTag()).checkBox.setTag(listCont.get(position));
            }
            ViewHolder holder = (ViewHolder) view.getTag();
            holder.text.setText(listCont.get(position).getName());
            holder.checkBox.setChecked(listCont.get(position).isSelected());




            holder.text = (TextView) view.findViewById(R.id.name);
            holder.photo = (ImageView) view.findViewById(R.id.photo);

            holder.textContNo = (TextView) view.findViewById(R.id.contactno);
            holder.textEmailId = (TextView) view.findViewById(R.id.emailId);

        Profile contact = listCont.get(position);
        holder.text.setText(contact.getName());
        contact.getName();
        contact.getId();

        holder.text.setTag(contact);
        holder.text.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Profile myContact= (Profile) v.getTag();

                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("city", myContact.getCity());
                intent.putExtra("state", myContact.getState());
                intent.putExtra("countryName", myContact.getCountryName());
                intent.putExtra("postalCode", myContact.getPostalCode());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 1");
                activity.setResult(100, intent);

                activity.finish();
                Constants.loadEntries.cancel(true);
                return false;
            }
        });



        if(contact.getPhoto() !=null && !contact.getPhoto().equals("")){
            viewHolder.photo.setImageBitmap(contact.getPhoto());
        }else{
            viewHolder.photo.setImageResource(R.drawable.profile);
        }

        holder.photo.setTag(contact);
        holder.photo.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Profile myContact= (Profile)v.getTag();

                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 2");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
                return false;
            }
        });

        holder.textContNo.setText(contact.getNumber());
        holder.textEmailId.setText(contact.getEmail());


        view.setClickable(true);
        view.setTag(contact);
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Profile myContact= (Profile) v.getTag();

                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 3");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
            }
        }); 

        LinearLayout layout = (LinearLayout)view.findViewById(R.id.profilelayout);
        layout.setTag(contact);
        layout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Profile myContact= (Profile) v.getTag();
                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                Log.d(TAG, "On Activity Result Method : 4");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
            }
        });



        if (position % 2 == 0) 
            view.setBackgroundResource(R.drawable.listshape); 
            else 
            view.setBackgroundResource(R.drawable.favoritebody); 

            if (contact.getAddress() != null && contact.getAddress().length() != 0){ 
                view.setBackgroundResource(R.drawable.hasaddress); 

            } 
            return view;
            } 

            }

when i check one checkbox and scrolling the check mark is repeating for few rows how to avoid that and i am gettign classcast exception at line

 ((ViewHolder) view.getTag()).checkBox.setTag(listCont.get(position));

Any help is appreciated.

teekib
  • 2,821
  • 10
  • 39
  • 75
  • Please paste your logcat. It will tell you "Class xxx cannot be cast to xxxx". – Lawrence Choy Jan 02 '13 at 12:24
  • @lawrence here is log http://pastebin.com/caNxYGNb – teekib Jan 02 '13 at 12:28
  • just remove view.setTag(contact) altogether. also, may too much code pasted, here. most of it not relevant. try to remove unrelevant parts. – njzk2 Jan 02 '13 at 13:10
  • @njzk2 yeah removed thatline ..but no change still getting same exception on the same line – teekib Jan 02 '13 at 13:15
  • remove this one as well `layout.setTag(contact);` I assume profilelayout is the root layout. (in which case, findViewById is useless there). You'll have a problem with the click listener and the getTag there, then – njzk2 Jan 02 '13 at 13:23
  • not getting any exception but...i checked one check box and scrolled and when i return the check mark disappeared and the imageviews are also changind ..wrong image are assigned to contacts – teekib Jan 02 '13 at 13:29

3 Answers3

1

Here is the problem, you called view.setTag(contact); in the middle of your code. So eventually the tag of your convertView is contact, not ViewHolder

Edit 1:

Replace

view.setTag(contact);

with

holder.checkBox.setTag(contact);

Edit 2: Ok I have added nizk2's comment to the answer. In addition, to fix your incorrect checkbox and image problem, please try the code below:

public ProfileAdapter(Activity activity, int textViewResourceId, List<Profile> listCont,int renderer, String profileType) {
        super(activity, textViewResourceId, listCont);
        this.renderer = renderer;
        this.listCont = listCont;
        this.activity = activity;
        this.profileType=profileType;

        checkBoxState=new boolean[listCont.size()];
    }

    private class ViewHolder
    {
      ImageView photo;
      TextView text,textContNo, textEmailId;
      CheckBox checkBox;
    }

    @TargetApi(9)
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

         View view = convertView;
         final Profile myContact = listCont.get(position);

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) (getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE));
            view = inflater.inflate(renderer, null);
             viewHolder=new ViewHolder();

             //cache the views
                viewHolder.photo=(ImageView) view.findViewById(R.id.photo);
                viewHolder.text=(TextView) view.findViewById(R.id.name);
                viewHolder.textContNo=(TextView) view.findViewById(R.id.contactno);
                viewHolder.textEmailId=(TextView) view.findViewById(R.id.emailId);
                viewHolder.checkBox=(CheckBox) view.findViewById(R.id.checkBox1);


              view.setTag(viewHolder);
            } else {
              view = convertView;
              ((ViewHolder) view.getTag()).checkBox.setTag(listCont.get(position));
            }
            ViewHolder holder = (ViewHolder) view.getTag();
            holder.text.setText(listCont.get(position).getName());
            holder.checkBox.setChecked(myContact.isSelected());
            viewHolder.checkBox
                  .setOnCheckedChangeListener(new                                                     CompoundButton.OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                      myContact.setSelected(buttonView.isChecked());
                    }
                  });

        holder.text.setText(myContact.getName());
        myContact.getName()
        myContact.getId();

        holder.text.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("city", myContact.getCity());
                intent.putExtra("state", myContact.getState());
                intent.putExtra("countryName", myContact.getCountryName());
                intent.putExtra("postalCode", myContact.getPostalCode());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 1");
                activity.setResult(100, intent);

                activity.finish();
                Constants.loadEntries.cancel(true);
                return false;
            }
        });



        if(myContact.getPhoto() !=null && !myContact.getPhoto().equals("")){
            viewHolder.photo.setImageBitmap(myContact.getPhoto());
        }else{
            viewHolder.photo.setImageResource(R.drawable.profile);
        }

        holder.photo.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {    
                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 2");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
                return false;
            }
        });

        holder.textContNo.setText(myContact.getNumber());
        holder.textEmailId.setText(myContact.getEmail());


        view.setClickable(true);
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                Log.d(TAG, "On Activity Result Method : 3");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
            }
        }); 

        LinearLayout layout = (LinearLayout)view.findViewById(R.id.profilelayout);
        layout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("type", profileType);
                intent.putExtra("name", myContact.getName());
                intent.putExtra("phoneNumber", myContact.getLandLineNo());
                intent.putExtra("email", myContact.getEmail());
                intent.putExtra("contactid", myContact.getId());
                intent.putExtra("address", myContact.getAddress());
                intent.putExtra("website", myContact.getWebSite());
                intent.putExtra("mobileNumber", myContact.getMobileNo());
                Log.d(TAG, "On Activity Result Method : 4");
                activity.setResult(100, intent);
                activity.finish();
                Constants.loadEntries.cancel(true);
            }
        });



        if (position % 2 == 0) 
            view.setBackgroundResource(R.drawable.listshape); 
            else 
            view.setBackgroundResource(R.drawable.favoritebody); 

            if (myContact.getAddress() != null && myContact.getAddress().length() != 0){ 
                view.setBackgroundResource(R.drawable.hasaddress); 

            } 
            return view;
            } 

            }
Lawrence Choy
  • 6,088
  • 1
  • 20
  • 30
-1

This expression: (ViewHolder) view.getTag()

You're casting a superclass into a subclass. getTag() returns an Object; the super-most class of all in Java. Casting it to a Subclass (your ViewHolder) is VERY VERY wrong (by wrong i mean unpredictable, because there are times it might work).

Upcasting is allowed in Java, however downcasting gives a compile error. The compile error can be removed by adding a cast but this would possibly break at the runtime.

Why is it wrong? Look here.

Community
  • 1
  • 1
varevarao
  • 2,186
  • 13
  • 26
  • Thank you and you are right...but that code i got it from a example which is working . – teekib Jan 02 '13 at 12:32
  • 1
    no. this is totally wrong. upcasting is automatic (anything is an object), downcasting is authorized (must be explicit, though), but dangerous, and tree verification is done at compile time. an object, being the tree root can be casted in anything. it fails at runtime only, if the object is not of the proper class. moreover, getTag returns an object, which you are expected to cast into whatever you put there. that's how it works in android. – njzk2 Jan 02 '13 at 13:09
  • _by wrong i mean unpredictable, because there are times it might work_ I say this and you say _downcasting is authorized (must be explicit, though), but dangerous_ and _it fails at runtime only_. Plus, I haven't said anything on whether or not Android finds this acceptable, I've just said it's bad, and unpredictable. – varevarao Jan 02 '13 at 13:13
  • 1
    unpredictable, but this is how tags are designed to work. `(ViewHolder) view.getTag()` is the very basis of the viewholder pattern – njzk2 Jan 02 '13 at 13:28
  • The implentation of `instanceof` is actually very useful to me. An application is always unpredictable, even thought you thought you have covered done all precautions. This is a great information, however, not an exact answer of this question. – Lawrence Choy Jan 02 '13 at 13:35
  • @njzk2, down-voting means information that is WRONG, not information pertaining to the subject but not exactly the answer (which is generally every answer apart from the accepted one on SO). None of what I've written is wrong or COMPLETELY irrelevant. Lawrence, I just thought it's worth mentioning on the subject given my bad experiences with the issue in the past. – varevarao Jan 02 '13 at 16:31
  • your answer is completely irrelevant to the question, as the question is basically "what's wrong with how i implement the viewholder pattern ?" and your answer is "the viewholder pattern is VERY VERY wrong" – njzk2 Jan 02 '13 at 16:33
  • Stating that downcasting gives compile error is incomplete and confusing, as you seem to use the term downcasting for implicit cast and cast for explicit cast. – njzk2 Jan 02 '13 at 16:35
  • You seem to read what you want to. Please complete the statement you mentioned in your second last comment, you'll see how I clarify that statement. P.S. In java, that generally is bad practice. – varevarao Jan 02 '13 at 16:37
  • Also, _completely irrelevant to the question_? I'm pretty sure the question mentioned a ClassCastException. This practice is a common source for that. – varevarao Jan 02 '13 at 16:39
  • @varevarao: Your answer *is* wrong. Casting is perfectly fine when used correctly, there is nothing unpredictable about it. Your answer is like saying that using division is wrong because you may divide by zero. – interjay Jan 02 '13 at 16:59
  • @interjay Parade around with the practice being right if you must (it probably is if you're sure about what you're doing), or just look [here in Wikipedia](http://en.wikipedia.org/wiki/Downcasting#Criticism) where it says _Many people advocate avoiding downcasting, since according to the LSP, an OOP design that requires it is flawed._ Sure it's useful, I just like to avoid it. So saying I'm wrong _is_ worng. – varevarao Jan 02 '13 at 17:08
  • Well, you didn't say that you advocate against downcasting, you said that it was "VERY VERY wrong" and unpredictable, which is completely different and highly misleading. And in any case this should have at most been a comment and not an answer. – interjay Jan 02 '13 at 17:12
  • Why don't people read beyond those words? I don't get it. I clarify what I mean by the oh so unholy "VERY VERY wrong" just after it. Please interpret it any way you wish, I have used grammar and syntax to the best of my ability in clarifying the answer, I won't stand corrected just because of your perspective of the words used being different. Someone found it useful, you didn't so assume this answer doesn't exist. :) – varevarao Jan 02 '13 at 17:18
-1

try this:

 CheckBox chB=(CkeckBox)((ViewHolder) view.getTag()).checkBox;
 chB.setTag(listCont.get(position));
Xenione
  • 2,174
  • 1
  • 23
  • 30
  • All you did was separate one line into two... Why do you think that will help? – interjay Jan 02 '13 at 12:46
  • becouse it's not the same. – Xenione Jan 02 '13 at 14:33
  • **How** is it not the same? What was wrong with the original code, and how does your answer fix it? Just blindly guessing is completely pointless, especially when all you do is rearrange the code a tiny bit. – interjay Jan 02 '13 at 15:32
  • you have a classcast exception probably becouse you are calling .setTag() inside a ViewHolder class, so casting could fix it. did you try? – Xenione Jan 02 '13 at 15:38