Android-адаптер с несколькими getView

Я читал о проблеме с вызовом getView несколько раз и обо всех ответах. Однако я не нахожу решения своей проблемы.

У меня есть список, в котором строки имеют два состояния: прочитано или нет. Ну, я хочу, чтобы элементы, увиденные в первый раз, имели другой цвет, и когда я прокручиваю список, они меняют свой цвет на «состояние чтения».

Для этого в методе getView моего адаптера я устанавливаю поле isRead, когда строка для этого элемента закрашивается. Но проблема в следующем: так как метод getView вызывается несколько раз, поле помечается как прочитанное, и когда список показывается на экране, он выглядит так, как будто он уже был прочитан.

Любая идея решить эту проблему?

Спасибо


person xger86x    schedule 07.07.2010    source источник


Ответы (4)


Я предполагаю, что вы имеете в виду проблему с запросом getView одного и того же представления несколько раз.

ListView делает это, потому что ему нужно получать измерения для представлений по разным причинам (размер полосы прокрутки, макет и т. д.).

Этой проблемы обычно можно избежать, не используя свойство «wrap_content» в вашем списке.

Кроме этого, использование getView для определения того, было ли отображено представление, просто плохая идея. В ListView есть много оптимизаций, которые мешают порядку вызова getView для каждой строки, поэтому невозможно узнать, что произойдет, и ваше приложение начнет демонстрировать странное поведение.

Старайтесь избегать любых отношений между представлением и данными, кроме концепции представления как отображения этих данных.

Вместо этого пусть какой-нибудь рабочий поток или прослушиватель событий в вашей деятельности по списку наблюдает за списком, для которого элементы в списке были показаны пользователю, обновляют данные и вызывают dataSetChanged на вашем адаптере.

person CodeFusionMobile    schedule 07.07.2010
comment
обновите данные и вызовите dataSetChanged на вашем адаптере - у меня работает - person Andrei Aulaska; 22.08.2013

У меня была та же проблема, и у меня вообще не было ссылки на «wrap_content» в атрибуте макетов. Хотя это старая тема, я не мог понять, как решить проблему. Таким образом, я смягчил это, добавив список в адаптер, который содержит уже нарисованные позиции, как показано в коде ниже. Я думаю, что это не правильно делать это сразу, но это сработало для меня.

public class ImageAdapter extends BaseAdapter {
    private Context mContext;
    private List<Integer> usedPositions  = new ArrayList<Integer>();

    public ImageAdapter(Context c, List<String> imageUrls) {
        mContext = c;
        ...
    }

    ...

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) { 
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        if (!usedPositions.contains(position)) {
            // Your code to fill the imageView object content
            usedPositions.add(position); // holds the used position
        }

        return imageView;
    }
}
person yguaratã    schedule 28.03.2011

Не так, как вы хотите, чтобы это работало. Причина, по которой getView() вызывается несколько раз, заключается в том, чтобы позволить ОС измерить строки, чтобы она знала, как их размещать. Вам нужно будет пометить его как прочитанное, когда они щелкнут по нему, отметят флажок или что-то в этом роде.

person CaseyB    schedule 07.07.2010

Вот очень простой способ избежать двойного вызова, когда вы знаете, что ничто ниже этого блока кода не исказит макет.

private static List<String> usedPositions  = new ArrayList<String>();

...

@Override
public View getView(int position, View rowView, ViewGroup parent) {
    rowView = inflater.inflate(R.layout.download_listview_item, null);

    Log.d(LOG_TAG, "--> Position: " + position);

    if (!usedPositions.contains(String.valueOf(position))){
        usedPositions.add(String.valueOf(position));
        return rowView;
    }else{
        usedPositions.remove(String.valueOf(position));
    }

...

person Kevin Parker    schedule 11.12.2011