0

I have created an adapter for a ListView in android which behaves really strange. The listview is passed a list of objects, which is sorted by some rule (comparing numbers, wow...). Now, when the list is shown in the view duplicate entries are shown, they are not sorted, entries are missing, and when I scroll the list even entries change! What is going on?

Here is the code of the adapter, I can post more code if that is necessary:

public class StatViewAdapter extends BaseAdapter {
 Activity activity;
 ArrayList<Entry> entries;
 TextView txtName;
 TextView txtOK;
 TextView txtNOK;
 TextView txtHist;
 TextView txtPrandom;
 TextView txtPhist;
 TextView txtPtotal;
 //public StatViewAdapter(Activity activity, ArrayList<HashMap<String, String>> list){
 public StatViewAdapter(Activity activity, ArrayList<Entry> entries){
 super();
 this.activity=activity;
 this.entries = entries;
 Collections.sort(this.entries, new Comparator<Entry>() {
 @Override
 public int compare(Entry o1, Entry o2) {
 if (o1.getPriority() > o2.getPriority()) {
 return 1;
 }
 if (o1.getPriority() < o2.getPriority()) {
 return -1;
 }
 return 0;
 }
 });
 for (int i=0;i<this.entries.size();i++) {
 String name = this.entries.get(i).name();
 int p = this.entries.get(i).getPriority();
 System.out.println(String.format("%s: %d", name, p));
 }
 }
 @Override
 public int getCount() {
 // TODO Auto-generated method stub
 //return list.size();
 return this.entries.size();
 }
 @Override
 public Object getItem(int position) {
 // TODO Auto-generated method stub
 return this.entries.get(position);
 }
 @Override
 public long getItemId(int position) {
 // TODO Auto-generated method stub
 return 0;
 }
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 // TODO Auto-generated method stub
 LayoutInflater inflater=this.activity.getLayoutInflater();
 if(convertView == null){
 convertView=inflater.inflate(R.layout.list_view, null);
 txtName=(TextView) convertView.findViewById(R.id.listname);
 txtOK=(TextView) convertView.findViewById(R.id.listok);
 txtNOK=(TextView) convertView.findViewById(R.id.listnok);
 txtHist=(TextView) convertView.findViewById(R.id.listhist);
 txtPrandom =(TextView) convertView.findViewById(R.id.listprandom);
 txtPhist=(TextView) convertView.findViewById(R.id.listphist);
 txtPtotal=(TextView) convertView.findViewById(R.id.listptot);
 }
 Entry entry = this.entries.get(position);
 txtName.setText(entry.name());
 txtOK.setText(Integer.toString(entry.number_ok));
 txtNOK.setText(Integer.toString(entry.number_nok));
 txtHist.setText(entry.history);
 txtPrandom.setText(Integer.toString(entry.randomIndex));
 txtPhist.setText(Integer.toString(entry.histIndex));
 txtPtotal.setText(Integer.toString(entry.getPriority()));
 return convertView;
 }
}
Chandan Rai
10.5k2 gold badges22 silver badges29 bronze badges
asked Jan 23, 2017 at 20:24
7
  • 1
    Obviously, because you are storing references to views of item directly in Adapter Commented Jan 23, 2017 at 20:25
  • what? can you explain? Its not obvious to me... Commented Jan 23, 2017 at 20:26
  • Analyze what would happen if convertView is not null but is not the same as last view returned from getView Commented Jan 23, 2017 at 20:28
  • I have not the slightest idea! Commented Jan 23, 2017 at 20:29
  • 1
    Too hard? All views references would be references to previous view not current... That's why viewholder pattern exits (not only) Commented Jan 23, 2017 at 20:30

1 Answer 1

2

The purpose of public View getView(int position, View convertView, ViewGroup parent) is to bind the data of the object at the given position to a view. The view might be a recycled one (convertView) or you need to create one in the method. The problem is that you should not keep references to those views (txtName, txtOk) in the Adapter.

public class StatViewAdapter extends BaseAdapter {
 Activity activity;
 ArrayList<Entry> entries;
 //TextView txtName;
 //TextView txtOK;
 // ...
 public StatViewAdapter(Activity activity, ArrayList<Entry> entries){
 // ...
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 LayoutInflater inflater=this.activity.getLayoutInflater();
 if(convertView == null){
 convertView=inflater.inflate(R.layout.list_view, null);
 }
 TextView txtName=(TextView) convertView.findViewById(R.id.listname);
 TextView txtOK=(TextView) convertView.findViewById(R.id.listok);
 // ...
 Entry entry = this.entries.get(position);
 txtName.setText(entry.name());
 txtOK.setText(Integer.toString(entry.number_ok));
 // ....
 return convertView;
 }

It works but it still isn't a good way to do it, you might want to use a RecyclerView or implement the ViewHolder pattern.

The idea of the ViewHolder pattern is that you don't have to call findViewById every time you bind a view because it's computationally expensive and it could make the scroll laggy.

You might want to use a RecyclerView because it's a newer and more flexible view that does the same job of a ListView and it has the ViewHolder pattern built-in.

OneCricketeer
193k20 gold badges147 silver badges277 bronze badges
answered Jan 23, 2017 at 20:31
Sign up to request clarification or add additional context in comments.

4 Comments

Nope, does not work. I see the same result. Maybe I have to clean the project. One moment ...
Ok this seems to work. But why is this not a good way. What is a RecyclerView? I don't want to recycle a view, just to present the data in the listview....?
I edited the answer for why it's not a good reason, also if it helped please consider accepting the answer :)
Seems I have to read some docs about this complicated stuff and those Views. Not today...

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.