ListView с чрезвычайно медленными изображениями

#java #android #performance #android-listview #bitmap

#java #Android #Производительность #android-listview #растровое изображение

Вопрос:

У меня есть a ListView , который отображает ImageView , чтобы показать пользователю обложку альбома и два TextView s для альбома и исполнителя.

Однако, когда я прокручиваю вверх и вниз, это всегда ужасно медленно.

 public class DSongListAdapter extends ArrayAdapter<Song> {

    Context mContext;
    List<Song> mObjects;

    public DSongListAdapter(Context context, List<Song> songList ) {
        super(context, R.layout.list_item_song, songList );
        this.mContext = context;
        this.mObjects = songList;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        if( convertView == null ){
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_song, parent, false);
            holder.titleLabel = (TextView) convertView.findViewById(R.id.titleLabel);
            holder.artistLabel = (TextView) convertView.findViewById(R.id.artistLabel);
            holder.cover = (ImageView) convertView.findViewById(R.id.list_image);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        holder.titleLabel.setText( mObjects.get(position).getTitle() );
        holder.artistLabel.setText( mObjects.get(position).getArtist() );
        Bitmap bm = SongManager.loadBitmap(mContext, mObjects.get(position).getAlbumId() );

        if( bm == null )
            holder.cover.setImageDrawable( mContext.getResources().getDrawable(R.drawable.untitled) );
        else
            holder.cover.setImageBitmap(bm);

        return convertView;
    }

    class ViewHolder {
        TextView titleLabel;
        TextView artistLabel;
        ImageView cover;
    }



}
  

Это адаптер списка, который я создал. SongManager.loadBitmap() Метод возвращает либо растровое изображение, либо значение null. Если оно равно нулю, я буду использовать растровое изображение по умолчанию из своих ресурсов.

Что я могу сделать, чтобы увеличить скорость?Например, музыкальный проигрыватель Amazon работает намного быстрее и плавнее, чем у меня! Также я заметил, что мое приложение занимает 42 МБ оперативной памяти. Это слишком много?

Редактировать:

 public static Bitmap loadBitmap( Context c, int album_id ){
    Bitmap bm = null;
    try {
        final Uri sArtworkUri = Uri
                .parse("content://media/external/audio/albumart");

        Uri uri = ContentUris.withAppendedId(sArtworkUri,
                album_id);

        ParcelFileDescriptor pfd = c.getContentResolver()
                .openFileDescriptor(uri, "r");

        if (pfd != null) {
            FileDescriptor fd = pfd.getFileDescriptor();
            bm = BitmapFactory.decodeFileDescriptor(fd);
        }
    } catch (Exception e) {

    }

    return bm;
}
  

Комментарии:

1. Каков размер / разрешение ваших изображений? Как это loadBitmap() выглядит? Кэширует ли он изображения, которые уже были загружены, или они каждый раз перезагружаются с диска?

2. Когда вы использовали Traceview, чтобы определить, в чем заключается ваша проблема, что вы узнали? Что вы узнали, когда вы включили StrictMode возможность видеть, выполняете ли вы сетевой или дисковый ввод-вывод в основном потоке приложения?

3. @CraigOtis Не знаю. Эти изображения находятся внутри файлов mp3 на моем устройстве. Они всегда перезагружаются с диска каждый раз, потому что я не знаю, как их кэшировать.

4. Это весь ваш loadBitmap() метод? Кажется, вы никогда ничего не назначаете Bitmap bm

5. @CraigOtis Извините, копирование не удалось: p Я опубликовал полный код.

Ответ №1:

Вы выполняете IPC и непрямой дисковый ввод-вывод при каждом getView() вызове. Если бы вы использовали Traceview, вы бы определили, что это источник вашей трудности.

Пожалуйста, рассмотрите возможность использования библиотеки, подобной Picasso, для асинхронной загрузки этих изображений и их кэширования. Существует много других подобных библиотек — см. Категории «Загрузчики изображений» и «Просмотр изображений» в арсенале Android.

Комментарии:

1. Спасибо!! это работает! Это даже уменьшило объем памяти с 42 МБ до 25 МБ.

Ответ №2:

Вы никогда не должны выполнять операции ввода-вывода в потоке пользовательского интерфейса. Вместо этого вы должны загружать свои изображения синхронно. К счастью, для этого есть множество хороших библиотек. Просто ознакомьтесь с этим, он прост в использовании и настройке: https://github.com/nostra13/Android-Universal-Image-Loader