ListView: convertView / держатель запутался - PullRequest
0 голосов
/ 23 марта 2010

Я работаю с ListView, пытаюсь заставить оптимизацию convertView / referenceHolder работать должным образом, но это доставляет мне проблемы. (Это система, в которой вы храните указатели R.id.xxx в качестве тега для каждого представления, чтобы избежать необходимости вызывать findViewById). У меня есть ListView, заполненный простыми строками ImageView и небольшим текстом, но ImageView можно отформатировать как для портретных изображений (высокий и узкий), так и для альбомных изображений (короткий и широкий). Он корректирует это форматирование для каждой строки, которая не работает, как я надеялся.

Основная система состоит в том, что для начала она раздувает макет каждой строки и устанавливает параметры ImageView на основе данных, а также включает int, обозначающий ориентацию в теге, содержащем значения R.id.xxx. Затем, когда он начинает повторно использовать convertViews, он проверяет эту сохраненную ориентацию по отношению к ориентации новой строки. Теория заключается в том, что если ориентация одинакова, то ImageView уже должен быть настроен правильно. Если это не так, тогда он соответствующим образом устанавливает параметры для ImageView и обновляет тег.

Однако я обнаружил, что это как-то запуталось; иногда тег может быть не синхронизирован с ориентацией ImageView. Например, тег будет по-прежнему говорить портрет, но фактический ImageView будет по-прежнему в альбомной ориентации. Я не мог найти образец того, как или когда это произошло; это не соответствовало ориентации, положению в списке или скорости прокрутки. Я могу решить эту проблему, просто сняв проверку ориентации convertView и просто всегда устанавливая параметры ImageView, но, похоже, это не соответствует цели этой оптимизации.

Кто-нибудь может увидеть, что я сделал неправильно в приведенном ниже коде?

static LinearLayout.LayoutParams layoutParams;
(...)

public View getView(int position, View convertView, ViewGroup parent){
    ReferenceHolder holder;

    if (convertView == null){
        convertView = inflater.inflate(R.layout.pick_image_row, null);
        holder = new ReferenceHolder();
        holder.getIdsAndSetTag(convertView, position);
        if (data[position][ORIENTATION] == LANDSCAPE) {
            // Layout defaults to portrait settings, so ImageView size needs adjusting. 
            // layoutParams is modified here, with specific values for width, height, margins etc
            holder.image.setLayoutParams(layoutParams);
        }
        holder.orientation = data[position][ORIENTATION];

    } else {
        holder = (ReferenceHolder) convertView.getTag();
        if (holder.orientation != data[position][ORIENTATION]){  //This is the key if statement for my question
            switch (image[position][ORIENTATION]) {
            case PORTRAIT:
                // layoutParams is reset to the Portrait settings
                holder.orientation = data[position][ORIENTATION];
                break;

            case LANDSCAPE:
                // layoutParams is reset to the Landscape settings
                holder.orientation = data[position][ORIENTATION];
                break;
            }
            holder.image.setLayoutParams(layoutParams);
        }               
    }

    // and the row's image and text is set here, using holder.image.xxx
    // and holder.text.xxx

    return convertView;
}

static class ReferenceHolder {
    ImageView image;
    TextView text;
    int orientation;

    void getIdsAndSetTag(View v, int position){
        image = (ImageView) v.findViewById(R.id.pickImageImage);
        text = (TextView) v.findViewById(R.id.pickImageText);
        orientation = data[position][ORIENTATION];
        v.setTag(this);
    }
}

Спасибо!

1 Ответ

2 голосов
/ 23 марта 2010

Вместо того, чтобы указывать ориентацию в качестве элемента данных ReferenceHolder, изучите фактический LayoutParams ImageView, чтобы увидеть, в какой он ориентации. Таким образом, по определению, вы не можете каким-то образом выйти из синхронизации .

Если честно, меня смущает код, который у вас там есть, так как вы, кажется, никогда не меняете layoutParams, что может показаться довольно важным. Или вы не должны иметь layoutParamsPortrait и layoutParamsLandscape или что-то еще? Для меня это выглядит так:

  • Если это портрет, а строка изначально создана, оставьте ее портрет
  • Все остальное является альбомным, независимо от того, что говорит флаг orientation, поскольку вы всегда устанавливаете его на layoutParams, что, вероятно, является альбомным
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...