2017-08-07 90 views
0

另一天,另一个问题!我目前正在为学校的作业创建一个音乐播放器。从第一天我创建和填充我的ListView时,ListView一直落后于疯狂。几天前,我开始用LruCache缓存图像,但没有注意到性能提升。今天我加入了ViewHolders,但是再次,没有任何性能增加。ListView滞后于ViewHolder和Cached图像

在我的ListView中,可以显示文件夹项目或歌曲项目。文件夹项目在他们的视图中获得了一张专辑图像(在2个文字浏览旁边)。现在它是从我的可绘制资源中绘制的一些硬编码图像(大小范围在15KB到55 KB之间)。一首歌曲项目只有4个TextViews。当名单只有歌曲项目时,滞后会少一些,但仍然太多。

目前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> 
+0

嵌套布局对性能不好(没有奇迹,你会落后!)。最好尝试使用RelativeLayouts。而ImageView是无用的,因为图像可以被包含到TextView中,作为**复合可绘制**。 –

+1

然后我会试着用相对的布局,而我从来没有听说过复合绘图!谢谢! –

+0

我更改了songs_list_item.xml以仅使用其中包含4个TextView的RelativeLayout,但延迟仍然差... –

回答

0

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

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

您必须在适配器外检索歌曲信息并将原始信息传递到适配器。

+0

我会试试这个吧! –

+0

它改善了性能很少,但它似乎不是这个问题的主要原因... –

+0

所以现在没有尝试/赶上IOException在适配器:: getView的权利?我在说,作为适配器内完整的IO操作删除的标识符。 –