0

Я создаю музыкальный плеер, который получает тег BP3 ID3v2 из всех mp3-файлов на устройстве и позволяет сортировать и фильтровать BPM. Чтобы получить тег, я использую библиотеку mp3agic. Оказывается, что для получения этой метки требуется некоторое время для каждой песни, и выполнение выборки при добавлении каждой песни в мой список песен временно покажет плеер. Я не уверен, должен ли я использовать AsyncTask во всем списке, когда это делается для создания или AsyncTask для каждого элемента, чтобы получить его BPM и вставить его в песню или даже с помощью другого более быстрого метода получения значения BPM. Может ли кто-нибудь предложить какие-либо указания?Выполнять медленную задачу по большому количеству данных в RecyclerView

Вот мой код, чтобы получить BPM:

public int getBpmFromId(long id) { 
    int bpm = -1; 
    Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, Long.toString(id)); 
    try { 
     Mp3File file = new Mp3File(getRealPathFromURI(getApplicationContext(), uri)); 
     if(file.hasId3v2Tag()) { 
      ID3v2 id3v2Tag = file.getId3v2Tag(); 
      bpm = id3v2Tag.getBPM(); 
      Log.d("MP3AGIC", "Got BPM for track: " + id + ": " + bpm); 

     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return bpm; 
} 

и вот код, я использую, чтобы построить свой список песен:

public void getSongList() { 
    ContentResolver musicResolver = getContentResolver(); 
    Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 

    String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?"; 
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0 AND " + selectionMimeType; 
    String sortOrder = null; 
    String[] projection = null; 
    String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp3"); 
    String[] selectionArgsMp3 = new String[] { mimeType }; 


    Cursor musicCursor = musicResolver.query(musicUri, projection, selection, selectionArgsMp3, sortOrder); 

    if(musicCursor != null && musicCursor.moveToFirst()) { 
     int idColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media._ID); 
     int titleColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE); 
     int artistColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST); 

     do { 
      long id = musicCursor.getLong(idColumn); 
      String title = musicCursor.getString(titleColumn); 
      String artist = musicCursor.getString(artistColumn); 

      //bpm processing 
      int bpm = getBpmFromId(id); 

      songList.add(new Song(id, title, artist)); 
     } while (musicCursor.moveToNext()); 
    } 
    if(musicCursor != null) 
     musicCursor.close(); 
} 

EDIT: Кажется, что то, что может быть так долго получает путь к файлу с Ури, что делается в этом методе:

public String getRealPathFromURI(Context context, Uri contentUri) { 
    Cursor cursor = null; 
    try { 
     String[] proj = { MediaStore.Images.Media.DATA }; 
     cursor = context.getContentResolver().query(contentUri, proj, null, null, null); 
     int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 
     cursor.moveToFirst(); 
     return cursor.getString(column_index); 
    } finally { 
     if (cursor != null) { 
      cursor.close(); 
     } 
    } 
} 

Я не знаю, как, или я Я могу, оптимизировать это.

ответ

0

Решение использовать одну асинтезу для всего списка или использовать список в качестве очереди для многих асинтетов зависит от вашего желания параллелизма.

  • Если вы планируете распараллеливать получение тегов, используйте несколько асинтактов (это было бы хорошо, если бы операция включала в себя много дискового ввода-вывода, а не процессорное время).
  • В противном случае, если вы планируете последовательно выполнять их, вы должны использовать только одну асинтезу. Нет необходимости создавать, а затем уничтожать десятки/сотни фоновых потоков. Это неэффективно.