Actuellement j'essaye de construire un lecteur de musique android à part entière. Je charge toutes les chansons, les artistes, les listes de lecture etc de mediastore chaque fois que l'application est chargée et précédemment pas présent dans RAM. Cette approche, bien que reflétant les changements de mediastore entre les charges d'application augmente considérablement le temps de chargement. Comment dois-je procéder pour obtenir des temps de chargement agréables et tenir compte des changements de données? Merci d'avance.Comment les lecteurs multimédias android natifs rendent les données persistantes et reflètent les changements
Répondre
Pour passer un curseur sur recyclerview adaptateur dans le Fragment mettre en œuvre LoaderManager
public class LayoutFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>
getLoaderManager().initLoader(0, null, LayoutFragment.this);
mAdapter = new LayoutAdapter(getActivity(),mRecyclerView,mLayoutId, mcursor);
mRecyclerView.setAdapter(mAdapter);
En outre, dans votre adaptateur, réglez la signature
public LayoutAdapter(Context context, RecyclerView recyclerView, int layoutId, Cursor c) {
mContext = context;
mCursor = c;
mRecyclerView = recyclerView;
mLayoutId = layoutId;
}
et ajoutez quelques méthodes parce que vous avez besoin à l'intérieur du fragment
@Override
public int getItemCount() {
if(mCursor!=null) {
return mCursor.getCount();
}else{
return 0;
}
}
public void swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return;
}
if (newCursor != null) {
mCursor = newCursor;
mRowIDColumn = mCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
// notify the observers about the new cursor
notifyDataSetChanged();
} else {
notifyItemRangeRemoved(0, getItemCount());
mCursor = null;
mRowIDColumn = -1;
mDataValid = false;
}
}
et Fragment
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER:
Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
final String criteria = null;
String[] columns = {
MediaStore.Audio.Playlists._ID,
MediaStore.Audio.Playlists.NAME,
};
return new CursorLoader(getActivity(), uri, columns, criteria, null, MediaStore.Audio.Playlists.NAME + " ASC");
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
mcursor=data;
mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
mcursor=null;
mAdapter.notifyDataSetChanged();
}
J'utilise une approche viewpager dans mon application New Playlist Manager, une pour toutes les pistes, albums et artistes. Pour chacun d'eux, j'ai un fragment dont chacun a un cursorAdapter personnalisé. Je vous donne l'exemple de toutes les pistes: mis en place mes colonnes:
dataColumns= new String[]{
MediaStore.Audio.Media.TRACK,
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.YEAR,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ALBUM_ID
};
sort_order = MediaStore.Audio.Media.TITLE +" ASC";
Pour remplir mon listView J'utilise un LoaderManager dans OnViewCreated
getLoaderManager().initLoader(GALLERY_LOADER, null, this);
et
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
switch (loaderID) {
case GALLERY_LOADER:
return new CursorLoader(getActivity(),
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
dataColumns,
null, null,
sort_order);
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
Alors Lorsque la vue a été créée, le LoaderManager récupère le curseur nécessaire qui est ensuite transmis à l'adaptateur. Ainsi, pour chacun des fragments, vous ne récupérez que les données dont vous avez besoin. Pour les albums Loader Cursor ressemble:
public class showallAlbumsFragment extends Fragment implements
OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor>
dataColumns= new String[]{
BaseColumns._ID,
AlbumColumns.ALBUM,
AlbumColumns.NUMBER_OF_SONGS,
AlbumColumns.FIRST_YEAR,
AlbumColumns.ARTIST };
sort_order = AlbumColumns.ALBUM +" ASC";
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
switch (loaderID) {
case GALLERY_LOADER:
return new CursorLoader(getActivity(),
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
dataColumns,
null, null,
sort_order);
default:
return null;
}
}
J'espère que cela vous fait aller
Merci, mais j'utilise une vue recycleur au lieu d'une vue en liste et il n'y a pas d'adaptateur de curseur pour la vue recycleur –
Peu importe. Vous devez savoir comment passer le curseur à recyclerview – Theo
Pourquoi ce auriez-vous besoin de charger toute la musique, etc. Vous simplement chercher dont vous avez besoin et quand vous en avez besoin. – Theo
Supposons que j'ai un viewpager avec des sections de chanson, album, liste de lecture, genre et ainsi de suite. Au strict minimum, j'ai besoin du nom et de l'identifiant de chaque catégorie. Encore je dois interroger la base de données entière, seulement le champ de filtrage sera rétréci. Maintenant, si je fais une requête chaque fois que je balaye le viewpager, l'interface utilisateur sera-t-elle lisse? J'ai 7,5 Go de chansons btw. –