ListView滞后于ViewHolder和Cached图像

时间:2017-08-07 13:31:43

标签: android listview lag

另一天,另一个问题!我目前正在为学校的作业创建一个音乐播放器。从我制作和填充ListView的第1天开始,ListView就像疯了似的一样。几天前,我开始使用LruCache缓存我的图像,但没有注意到性能提升。今天我在ViewHolders中添加了,但同样,没有任何性能提升。

在我的ListView中,可以显示文件夹项目或歌曲项目。文件夹项目在其视图中显示相册图像(2个文本视图旁边)。现在它是从我的可绘制资源中抽取的一些硬编码图像(大小范围在15KB到55KB之间)。一首歌曲项目只有4个TextView。当列表只有歌曲项目时,滞后会少一点,但仍然太多。

目前ListView中最多有10个项目。下面是用于创建列表的ArrayAdapter。我对Android非常陌生,所以任何帮助/提示都会受到赞赏,即使它与此问题无关。

public class SongAdapter extends ArrayAdapter{

    private final LruCache<String, Bitmap> cache;
    private ArrayList<Integer> myFolderSongCounts;

    ViewHolderSongs holderSongs;
    ViewHolderFolders holderFolders;

    public SongAdapter(Context context, List objects, ArrayList<Integer> folderSongCounts) {
        super(context, 0, objects);

        myFolderSongCounts = folderSongCounts;

        /*
        *
        * CACHE EXAMPLE FROM
        * https://stackoverflow.com/questions/15586977/listview-scroll-lagging-when-images-is-shown
        * BY USER Lam Do
        *
        * */

        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        // Use 1/8th of the available memory for this memory cache.
        final int cacheSize = maxMemory / 8;

        cache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // The cache size will be measured in kilobytes rather than
                // number of items.
                return bitmap.getRowBytes() / 1024;
            }
        };

    }

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

        File song = (File) getItem(position);

        Log.d("SongAdapter Position: ", ""+ position);

        Listen main = (Listen) getContext().getApplicationContext();
        Typeface custom_font = main.getCustom_font();

        //if its an mp3 file, show a song list item
        if(song.getName().substring(song.getName().length()-4,song.getName().length()).equals(".mp3")) {
            Mp3File mp3file = null;
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(song.getPath());
            try {
                if(convertView == null){
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.songs_list_item, parent, false);

                    holderSongs = new ViewHolderSongs();
                    holderSongs.txt_song_album = (TextView) convertView.findViewById(R.id.song_album);
                    holderSongs.txt_song_artist = (TextView) convertView.findViewById(R.id.song_artist);
                    holderSongs.txt_song_duration = (TextView) convertView.findViewById(R.id.song_duration);
                    holderSongs.txt_song_name = (TextView) convertView.findViewById(R.id.song_name);

                    convertView.setTag(holderSongs);
                }
                else {
                    holderSongs = (ViewHolderSongs) convertView.getTag();
                }

                mp3file = new Mp3File(song);

                String album = mp3file.getId3v2Tag().getAlbum();
                String artist = mp3file.getId3v2Tag().getAlbumArtist();

                int durationInMilliseconds = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
                int durationInSeconds = durationInMilliseconds/1000;
                int durationMinutes = durationInSeconds/60;
                String durationSeconds = (durationInSeconds%60 > 10) ? "" + durationInSeconds%60 : "0" + durationInSeconds%60;
                String duration = durationMinutes + ":" + durationSeconds;

                holderSongs.txt_song_name.setText(song.getName().substring(0, song.getName().length() - 4));
                holderSongs.txt_song_album.setText(getValidValue(album, "undefined"));
                holderSongs.txt_song_artist.setText(getValidValue(artist, "undefined"));
                holderSongs.txt_song_duration.setText(getValidValue(duration, "0:00"));

                holderSongs.txt_song_name.setTypeface(custom_font);
                holderSongs.txt_song_album.setTypeface(custom_font);
                holderSongs.txt_song_artist.setTypeface(custom_font);
                holderSongs.txt_song_duration.setTypeface(custom_font);

            } catch (IOException e) {
                e.printStackTrace();
            } catch (UnsupportedTagException e) {
                e.printStackTrace();
            } catch (InvalidDataException e) {
                e.printStackTrace();
            }
        }
        //if its a folder, show a folder list item
        else {
            if(convertView == null){
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.folders_list_item, parent, false);

                holderFolders = new ViewHolderFolders();

                holderFolders.amount_of_songs = (TextView)convertView.findViewById(R.id.amount_of_songs);
                holderFolders.folder_name = (TextView)convertView.findViewById(R.id.folder_name);
                holderFolders.folder_image = (ImageView)convertView.findViewById(R.id.folder_image);

                convertView.setTag(holderFolders);
            }
            else {
                holderFolders = (ViewHolderFolders) convertView.getTag();
            }


            int amountOfSongs = myFolderSongCounts.get(position);

            holderFolders.folder_name.setText(song.getName());
            holderFolders.amount_of_songs.setText(amountOfSongs + " songs");

            holderFolders.folder_name.setTypeface(custom_font);
            holderFolders.amount_of_songs.setTypeface(custom_font);

            if(position == 0){

                Bitmap bmp = getBitmapFromMemCache("perfectlychilled");
                if (bmp == null) {
                    bmp = BitmapFactory.decodeResource(convertView.getResources(), R.drawable.perfectly_chilled);
                    addBitmapToMemoryCache("perfectlychilled", bmp);
                }

                holderFolders.folder_image.setImageBitmap(bmp);
            }
            else if(position == 1){
                Bitmap bmp = getBitmapFromMemCache("insurgency");
                if (bmp == null) {
                    bmp = BitmapFactory.decodeResource(convertView.getResources(), R.drawable.insurgency);
                    addBitmapToMemoryCache("insurgency", bmp);
                }

                holderFolders.folder_image.setImageBitmap(bmp);
            }
            else {
                Bitmap bmp = getBitmapFromMemCache("default");
                if (bmp == null) {
                    bmp = BitmapFactory.decodeResource(convertView.getResources(), R.drawable.folderdefault);
                    addBitmapToMemoryCache("default", bmp);
                }

                holderFolders.folder_image.setImageBitmap(bmp);
            }
        }



        return convertView;
    }

    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            cache.put(key, bitmap);
        }
    }

    public Bitmap getBitmapFromMemCache(String key) {
        return cache.get(key);
    }

    static class ViewHolderSongs {
        TextView txt_song_name;
        TextView txt_song_album;
        TextView txt_song_artist;
        TextView txt_song_duration;
    }

    static class ViewHolderFolders {
        TextView folder_name;
        TextView amount_of_songs;
        ImageView folder_image;
    }
}

songs_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_margin="0dp"
    android:padding="0dp"
    android:background="@color/backgroundGray"
    android:gravity="center_vertical"
    android:layout_height="70dp">

        <TextView
            android:text="TextView"
            android:layout_width="280dp"
            android:layout_height="wrap_content"
            android:paddingLeft="15dp"
            android:paddingRight="20dp"
            android:id="@+id/song_name"
            android:textColor="@color/textBlack"
            android:maxLines="1"
            android:layout_marginBottom="8dp"
            android:ellipsize="end" />

        <TextView
            android:text="3:26"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:textAlignment="textEnd"
            android:paddingRight="15dp"
            android:maxLines="1"
            android:ellipsize="end"
            android:textColor="@color/textBlack"
            android:layout_toRightOf="@id/song_name"
            android:id="@+id/song_duration"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/song_artist"
            android:textColor="@color/textGray"
            android:width="190dp"
            android:gravity="bottom"
            android:maxLines="1"
            android:ellipsize="end"
            android:layout_below="@id/song_name"
            android:paddingRight="20dp"
            android:paddingLeft="15dp"
            android:text="Sabaton" />

        <TextView
            android:text="Hell is upon us"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/textGray"
            android:width="190dp"
            android:id="@+id/song_album"
            android:paddingRight="15dp"
            android:textAlignment="textEnd"
            android:maxLines="1"
            android:ellipsize="end"
            android:layout_below="@id/song_name"
            android:layout_toRightOf="@id/song_artist"
            />

</RelativeLayout>

folders_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_marginTop="0dp"
    android:layout_marginBottom="0dp"
    android:background="@color/backgroundGray"

    android:padding="0dp"
    android:layout_height="115dp">

    <ImageView
        android:layout_height="match_parent"
        android:id="@+id/folder_image"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:padding="0dp"
        android:layout_width="115dp" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"

        android:padding="0dp"
        android:layout_marginLeft="30dp">

        <TextView
            android:layout_marginTop="0dp"
            android:layout_marginBottom="0dp"
            android:padding="0dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/folder_name"
            android:layout_weight="50"
            android:elevation="14dp"
            android:textIsSelectable="false"
            android:gravity="bottom"
            android:paddingBottom="5dp"
            android:textAppearance="@android:style/TextAppearance.Material.Medium"
            android:textColor="@color/textBlack"/>

        <TextView
            android:layout_marginTop="0dp"
            android:layout_marginBottom="0dp"
            android:paddingTop="5dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/amount_of_songs"
            android:layout_weight="50"
            android:textColor="@color/textGray"/>
    </LinearLayout>

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

文档https://developer.android.com/reference/android/media/MediaMetadataRetriever.html

- 的setDataSource 设置要使用的数据源(FileDescriptor)。关闭文件描述符是调用者的责任。一旦此呼叫返回,这样做是安全的。在此类的其余方法之前调用此方法。 此方法可能非常耗时。

你必须检索歌曲&#39;适配器外部的信息,并将原始信息传递到适配器。