BaseAdapter заставляет ListView выходить из строя при прокрутке - PullRequest
9 голосов
/ 26 июня 2010

У меня проблемы с кодом BaseAdapter, который я адаптировал из книги.Я использовал варианты этого кода повсюду в моем приложении, но только что понял, что при прокрутке длинного списка элементы в ListView перемешиваются, и не все элементы отображаются.Трудно описать точное поведение, но легко увидеть, если вы возьмете отсортированный список из 50 пунктов и начнете прокручивать вверх и вниз.

class ContactAdapter extends BaseAdapter {

    ArrayList<Contact> mContacts;

    public ContactAdapter(ArrayList<Contact> contacts) {
        mContacts = contacts;
    }

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

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

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        if(convertView == null){
            LayoutInflater li = getLayoutInflater();
            view = li.inflate(R.layout.groups_item, null);
            TextView label = (TextView)view.findViewById(R.id.groups_item_title);
            label.setText(mContacts.get(position).getName());
            label = (TextView)view.findViewById(R.id.groups_item_subtitle);
            label.setText(mContacts.get(position).getNumber());
        }
        else
        {
            view = convertView;
        }
        return view;
    }

}

Ответы [ 2 ]

13 голосов
/ 26 июня 2010

Вы помещаете данные в виджеты TextView только при их первом создании. Вам нужно переместить эти четыре строки:

        TextView label = (TextView)view.findViewById(R.id.groups_item_title);
        label.setText(mContacts.get(position).getName());
        label = (TextView)view.findViewById(R.id.groups_item_subtitle);
        label.setText(mContacts.get(position).getNumber());

должно быть после блока if / else и до возврата метода, поэтому вы обновляете виджеты TextView независимо от того, перерабатываете ли вы строку или создаете новую.

5 голосов
/ 10 января 2012

Чтобы дополнительно уточнить ответ CommonsWare, вот еще некоторая информация:

Операция li.inflate (необходима здесь для анализа разметки строки из XML и созданиясоответствующий объект вида) оборачивается оператором if (convertView == null) для повышения эффективности, поэтому раздувание одного и того же объекта не будет происходить снова и снова каждый раз, когда он появляется в представлении.

ОДНАКО другие части метода getView используются для установки других параметров и поэтому НЕ должны включаться в if (convertView == null) {} ... else {} .

Во многих распространенных реализациях этого метода некоторые элементы textView label, ImageView или ImageButton должны заполняться значениями из списка [position], используя findViewById и после этого .setText или .setImageBitmap операций.Эти операции должны выполняться после того, как и создадут представление с нуля с помощью инфляции и , получая существующее представление, если оно не равно нулю (например, при обновлении).

Еще один хороший пример, гдеэто решение применяется для ListView ArrayAdapter появляется в https://stackoverflow.com/a/3874639/978329

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...