0

~~Bugs screen caps~~Listview icon appear in wrong row when scroll down then scroll up, the error imageview is tvType, but when i refreshed, everything are right. thanks for your help.

private class HistoryAdapter extends BaseAdapter implements Filterable {

    private ArrayList<Historyinfo> _History;
    private ValueFilter valueFilter;
    private ArrayList<Historyinfo> mStringFilterList;
    private LayoutInflater layoutInflater;

    public HistoryAdapter(Context context, ArrayList<Historyinfo> _History){
        super();
        this._History = _History;
        mStringFilterList = _History;
        layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        getFilter();
    }

    @Override
    public int getCount() {
        return _History.size();
    }

    @Override
    public Object getItem(int position) {
        return _History.get(position);
    }

    @Override
    public long getItemId(int position) {
        return _History.get(position).getID();
    }

            @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null){
            convertView= layoutInflater.inflate(R.layout.listview_historyitem,parent,false);
        }
        Historyinfo historyinfo = _History.get(position);



      ImageView tvType = (ImageView)convertView.findViewById(R.id.tvType);
        TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
        TextView tvDate = (TextView)convertView.findViewById(R.id.tvDate);


        if (Studentinfo.stuID.equals(historyinfo.actOrganizer)){
            tvType.setVisibility(View.VISIBLE);
            switch (Studentinfo.stuSex){
                case "M":
                    tvType.setImageResource(R.drawable.circled_user_male);
                    break;
                case "F":
                    tvType.setImageResource(R.drawable.circled_user_female_skin_type_4);
                    break;
               // default:tvType.setVisibility(View.GONE);
            }
        }
        else {
            tvType.setVisibility(View.GONE);
        }


        tvName.setText(historyinfo.getName());
        tvDate.setText(historyinfo.getDate());

        return convertView;



    }
    @Override
    public Filter getFilter() {
        if(valueFilter==null) {

            valueFilter=new ValueFilter();
        }

        return valueFilter;
    }

    private class ValueFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results=new FilterResults();
            if(constraint!=null && constraint.length()>0){
                ArrayList<Historyinfo> filterList= new ArrayList<>();
                for(int i=0;i<mStringFilterList.size();i++){
                    if((mStringFilterList.get(i).getName().toUpperCase())
                            .contains(constraint.toString().toUpperCase())||
                            (mStringFilterList.get(i).getType().toUpperCase())
                                    .contains(constraint.toString().toUpperCase())) {
                        Historyinfo contacts = new Historyinfo();
                        contacts.setActID(String.valueOf(mStringFilterList.get(i).getID()));
                        contacts.setActType(mStringFilterList.get(i).getType());
                        contacts.setActName(mStringFilterList.get(i).getName());
                        contacts.setActDate(mStringFilterList.get(i).getDate());
                        contacts.setActTime(mStringFilterList.get(i).getTime());
                        contacts.setActContent(mStringFilterList.get(i).getContent());
                        contacts.setActQuota(mStringFilterList.get(i).getQuota());
                        contacts.setActOrganizer(mStringFilterList.get(i).getOrganizer());

                        filterList.add(contacts);
                    }
                }
                results.count=filterList.size();
                results.values=filterList;
            }else{
                results.count=mStringFilterList.size();
                results.values=mStringFilterList;
            }
            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            _History=(ArrayList<Historyinfo>) results.values;
            notifyDataSetChanged();
        }
    }

}
karl
  • 91
  • 7
  • 1
    Please be more descriptive or attach an image. – Vucko Jul 15 '16 at 16:07
  • 1
    Your switch statement using a static variable is very likely your issue. – zgc7009 Jul 15 '16 at 16:31
  • added the bug's cap screen for explanation, please take a look, bros – karl Jul 16 '16 at 17:52
  • What is `Studentinfo` - a class name or a variable name? It's difficult to tell because your code does not consistently follow typical Java naming conventions (lower case first letter for variable name, optionally prefixed with a lowercase 'm' for instance variables, and capital letter for class names) – PPartisan Jul 17 '16 at 14:55

1 Answers1

1

The problem is, most likely, with extending BaseAdapter.

In short, there are two methods that we should take a deeper look at, in Adapter interface:

getItemViewType(int position);
getViewTypeCount()

And its implementation in BaseAdapter

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

Those methods are very useful for ListView. You can take a deeper look into how ListView works and recycles views in here but in short: Whenever new view is about to occur, ListView asks adapter for its type and checks, whether it does not already have a view of the same type. If so, it passes it to getView as a convertView parameter.

If this is the case while loading one of views, then this is the "base" view you are starting with in your getView code, which is perfectly fine and improves performance a lot.

The problem occurs, when this code would not execute in your Adapter:

if (Studentinfo.stuID.equals(historyinfo.actOrganizer)){
        switch (Studentinfo.stuSex){
            case "M":
                tvType.setImageResource(R.drawable.circled_user_male);
                break;
            case "F":
                tvType.setImageResource(R.drawable.circled_user_female_skin_type_4);
                break;
        }
    }

Which might happen, when stuSex is null, for instance. And if this happens, then for the row being created an image from convertView is used (which might be different on different cases).

The simpliest solution would be adding default for your case statement and set image to empty one in there.

More sophisticated one would be to override getViewTypeCount method to return 3 and getItemViewType to return 0 for male student, 1 for female and 2 for others. This would be better both in style, code readibility and, most of all, performance.

Community
  • 1
  • 1
mis3k
  • 144
  • 1
  • 8
  • problem still here when i added the default case for switch, how can i use the those methods to debug my bugs? i have no idea to use because i did not use it before, moreover, i added the bug's cap screen, please take a look, thank you at all mis3k ! – karl Jul 16 '16 at 17:51
  • Please add in default case the code tvType.setVisibility(View.GONE) and let me know if that helps. – mis3k Jul 16 '16 at 18:33
  • Finally, i put the tvType.setVisibility(View.VISIBLE); in the if case, and tvType.setVisibility(View.GONE); in the else case, the problem is solved, but it seems not perfect as it only controlling the visibility, i think some icons still display in wrong row in fact. – karl Jul 17 '16 at 03:03
  • I am pretty sure that the problem lays in logic of if-else statement and switch-case block. It is very difficult to guess what is going on there... Could you please update your question with current code from getView method? – mis3k Jul 17 '16 at 09:24
  • So there still must be some problem with switch-case logic. Please add some Log.d() in both cases and observe if they are invoked correctly. They shall be logged whenever a row appears on the screen. – mis3k Jul 18 '16 at 08:27