Подтвердить что ты не робот

Как загрузить Listview "плавно" в android

Я загружаю данные из Cursor в listview, но мой Listview действительно не отображается "плавным". Данные меняются при перетаскивании вверх и вниз на панели scollbar в моем ListView. И некоторые элементы выглядят как дублированный дисплей в моем списке. Я hava "сложный ListView" (два textview, oneviewview). Поэтому я использовал newView(), bindView() для отображения данных. Кто-нибудь может мне помочь?

4b9b3361

Ответ 1

Я расскажу вам, как получить такую ​​проблему, которая у вас есть. Возможно, это поможет вам.

Итак, в адаптере списка у вас есть такой код:

public View getView(int position, View contentView, ViewGroup arg2)
    {
        ViewHolder holder;

        if (contentView == null) {
            holder = new ViewHolder();
            contentView = inflater.inflate(R.layout.my_magic_list,null);
            holder.label = (TextView) contentView.findViewById(R.id.label);
            contentView.setTag(holder);
        } else {
            holder = (ViewHolder) contentView.getTag();
        }

        holder.label.setText(getLabel());

        return contentView;
    }

Как вы можете видеть, мы устанавливаем значение элемента списка только после того, как мы получили владельца.

Но если вы переводите код в вышеприведенный оператор if:

holder.label.setText(getLabel());

поэтому он будет выглядеть следующим образом:

if (contentView == null) {
   holder = new ViewHolder();
   contentView = inflater.inflate(R.layout.my_magic_list,null);
   holder.label = (TextView) contentView.findViewById(R.id.label);
   holder.label.setText(getLabel());
   contentView.setTag(holder);
}

у вас будет текущее поведение приложения с дублированием элемента списка.

Возможно, это поможет.

Ответ 2

ListView - хитрый зверь.

Второй вопрос: вы видите дубликаты, потому что ListView повторно использует Views через convertView, но вы не следите за reset всеми аспектами преобразованного представления. Убедитесь, что путь кода для convertView!=null правильно задает все данные для представления, и все должно работать должным образом.

Вы хотите, чтобы ваш метод getView() выглядел примерно следующим образом, если вы используете пользовательские представления:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView();
    v.setMyData( listAdapter.get(position) );
    return v;
}

Если вы не используете собственное собственное представление, просто замените вызов на new MyCustomView() вызовом inflater.inflate(R.layout.my_layout,null)

Что касается вашего первого вопроса, вам нужно посмотреть, как Romain techtalk показывает производительность ListView здесь: http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

Из своего разговора и в порядке важности из моего собственного опыта,

  • Использовать convertView
  • Если у вас есть изображения, не масштабируйте свои изображения "на лету". Используйте Bitmap.createScaledBitmap для создания масштабированного растрового изображения и поместите его в свои представления.
  • Используйте ViewHolder, поэтому вам не нужно каждый раз называть группу findViewByIds()
  • Уменьшить сложность просмотров в списке. Чем меньше подпунктов, тем лучше. RelativeLayout намного лучше, чем, скажем, LinearLayout. И обязательно используйте, если вы реализуете пользовательские представления.

Ответ 3

Я тоже сталкиваюсь с этой проблемой, но в моем случае я использовал потоки для получения внешних изображений. Важно, чтобы текущий исполняемый поток не менял imageView, если он повторно используется!

public View getView(int position, View vi, ViewGroup parent) {
ViewHolder holder;
String imageUrl = ...;

if (vi == null) {
    vi = inflater.inflate(R.layout.tweet, null);
    holder = new ViewHolder();
    holder.image = (ImageView) vi.findViewById(R.id.row_img);
    ...
    vi.setTag(holder);
} else {
    holder = (ViewHolder) vi.getTag();      
}
holder.image.setTag(imageUrl);
...
DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image);
}

И затем в извлечении потока я делаю важную проверку:

final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
     // VERY IMPORTANT CHECK
    if (urlString.equals(url))
        imageView.setImageDrawable((Drawable) message.obj);
};

Thread thread = new Thread() {  

@Override
public void run() {
    Drawable drawable = fetchDrawable(urlString);
    if (drawable != null) {
        Message message = handler.obtainMessage(1, drawable);
        handler.sendMessage(message);
    }
}};
thread.start();

Можно также отменить текущий поток, если их представление будет повторно использовано (как описано здесь), но я решил против этого, потому что хочу для заполнения моего кеша для последующего повторного использования.

Ответ 4

Только один совет: НИКОГДА не используйте прозрачный фон макета элемента - он значительно замедляет производительность.

Ответ 5

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