本机 android 媒体播放器如何使数据持久化并反映变化
How do native android media players make data persistent as well as reflect changes
目前我正在尝试构建一个完整的 android 音乐播放器。每当应用程序加载并且以前不存在于 ram 中时,我都会从 mediastore 加载所有歌曲、艺术家、播放列表等。这种方法虽然反映了应用程序加载之间的 mediastore 变化,但大大增加了加载时间。我应该如何着手获得满意的加载时间并反映任何数据更改?提前致谢。
我在我的应用 New Playlist Manager 中使用了一种 viewpager 方法,一种用于所有曲目、专辑和艺术家的方法。对于其中的每一个,我都有一个片段,每个片段都有一个自定义的 cursorAdapter。
我给你所有轨道的例子:
设置我的专栏:
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";
为了填充我的 listView,我使用了 LoaderManager
在 OnViewCreated
getLoaderManager().initLoader(GALLERY_LOADER, null, this);
和
@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);
}
因此,在创建视图后,LoaderManager 获取必要的游标,然后将其提供给适配器。
所以对于每个片段,你只需要获取你需要的数据。
对于相册,我的 Cursor Loader 看起来像:
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;
}
}
我希望这能让你前进
将光标传递给 recyclerview 适配器
其中,Fragment实现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);
此外,在您的适配器中,调整签名
public LayoutAdapter(Context context, RecyclerView recyclerView, int layoutId, Cursor c) {
mContext = context;
mCursor = c;
mRecyclerView = recyclerView;
mLayoutId = layoutId;
}
并添加一些方法,因为您需要从片段中获取它们
@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;
}
}
在片段中
@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();
}
目前我正在尝试构建一个完整的 android 音乐播放器。每当应用程序加载并且以前不存在于 ram 中时,我都会从 mediastore 加载所有歌曲、艺术家、播放列表等。这种方法虽然反映了应用程序加载之间的 mediastore 变化,但大大增加了加载时间。我应该如何着手获得满意的加载时间并反映任何数据更改?提前致谢。
我在我的应用 New Playlist Manager 中使用了一种 viewpager 方法,一种用于所有曲目、专辑和艺术家的方法。对于其中的每一个,我都有一个片段,每个片段都有一个自定义的 cursorAdapter。 我给你所有轨道的例子: 设置我的专栏:
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";
为了填充我的 listView,我使用了 LoaderManager 在 OnViewCreated
getLoaderManager().initLoader(GALLERY_LOADER, null, this);
和
@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);
}
因此,在创建视图后,LoaderManager 获取必要的游标,然后将其提供给适配器。 所以对于每个片段,你只需要获取你需要的数据。 对于相册,我的 Cursor Loader 看起来像:
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;
}
}
我希望这能让你前进
将光标传递给 recyclerview 适配器 其中,Fragment实现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);
此外,在您的适配器中,调整签名
public LayoutAdapter(Context context, RecyclerView recyclerView, int layoutId, Cursor c) {
mContext = context;
mCursor = c;
mRecyclerView = recyclerView;
mLayoutId = layoutId;
}
并添加一些方法,因为您需要从片段中获取它们
@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;
}
}
在片段中
@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();
}