手把手教你做音樂播放器(五)音樂列表的儲存(下)
5.2 MusicService的配合
MusicService
對外提供新增播放列表的介面,對內要管理PlayListContentProvider
。它提供了下面的介面,
addPlayList():新增播放列表。這裡新增列表應該有兩種形式,一種是一次性新增多首音樂,一種是一次就新增一首音樂。
getPlayList():獲取播放列表
播放列表要儲存到一個數組裡面,所以我們要建立一個mPlayList
實現列表的儲存,
public class MusicService extends Service {
private List<MusicItem> mPlayList;
private ContentResolver mResolver;
@Override
public void onCreate() {
super.onCreate();
//獲取ContentProvider的解析器,避免以後每次使用的時候都要重新獲取
mResolver = getContentResolver();
//儲存播放列表
mPlayList = new ArrayList<MusicItem>();
}
}
5.2.1 新增播放列表
addPlayList()
應該有兩種形式,一次新增一首音樂和一次新增多首音樂。
public class MusicService extends Service {
public class MusicServiceIBinder extends Binder {
......
//一次新增多首音樂
public void addPlayList(List<MusicItem> items) {
addPlayListInner(items);
}
//一次新增一首音樂
public void addPlayList(MusicItem item) {
addPlayListInner(item);
}
}
//一次新增多首音樂具體實現
private void addPlayListInner(List<MusicItem> items) {
}
//一次新增一首音樂具體實現
private void addPlayListInner(MusicItem item) {
}
}
5.2.1.1 新增一首音樂
private void addPlayListInner(MusicItem item) {
//判斷列表中是否已經儲存過該音樂,如果儲存過就不管它
if(mPlayList.contains(item)) {
return;
}
//新增到播放列表的第一個位置
mPlayList.add(0, item);
//將音樂資訊儲存到ContentProvider中
insertMusicItemToContentProvider(item);
}
//訪問ContentProvider,儲存一條資料
private void insertMusicItemToContentProvider(MusicItem item) {
ContentValues cv = new ContentValues();
cv.put(DBHelper.NAME, item.name);
cv.put(DBHelper.DURATION, item.duration);
cv.put(DBHelper.LAST_PLAY_TIME, item.playedTime);
cv.put(DBHelper.SONG_URI, item.songUri.toString());
cv.put(DBHelper.ALBUM_URI, item.albumUri.toString());
Uri uri = mResolver.insert(PlayListContentProvider.CONTENT_SONGS_URI, cv);
}
判斷mPlayList
是否儲存了音樂,需要對MusicItem
做特別的處理:給它定義一個比較的準則–什麼情況下兩個相比較的內容是相同的。我們這個例子當中,應該是音樂的Uri相同,則認為兩者相同。重寫MusicItem
的equals()
方法,當使用mPlayList.contains(item)
判斷的時候,會呼叫到這個重寫的方法進行比較,
public class MusicItem {
......
//重寫MusicItem的equals()方法
@Override
public boolean equals(Object o) {
MusicItem another = (MusicItem) o;
//音樂的Uri相同,則說明兩者相同
return another.songUri.equals(this.songUri);
}
}
5.2.1.2 新增多首音樂
private void addPlayListInner(List<MusicItem> items) {
//清空資料庫中的playlist_table
mResolver.delete(PlayListContentProvider.CONTENT_SONGS_URI, null, null);
//清空快取的播放列表
mPlayList.clear();
//將每首音樂新增到播放列表的快取和資料庫中
for (MusicItem item : items) {
//利用現成的程式碼,便於程式碼的維護
addPlayListInner(item);
}
}
5.2.2 獲取播放列表
為了獲取播放列表在ContentProvider
啟動的時候,需要它將資料庫中現有的列表,載入到mPlayList
當中,
public class MusicService extends Service {
@Override
public void onCreate() {
super.onCreate();
......
initPlayList();
......
}
private void initPlayList() {
mPlayList.clear();
Cursor cursor = mResolver.query(
PlayListContentProvider.CONTENT_SONGS_URI,
null,
null,
null,
null);
while(cursor.moveToNext()) {
String songUri = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.SONG_URI));
String albumUri = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.ALBUM_URI));
String name = cursor.getString(cursor.getColumnIndex(DBHelper.NAME));
long playedTime = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LAST_PLAY_TIME));
long duration = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.DURATION));
MusicItem item = new MusicItem(Uri.parse(songUri), Uri.parse(albumUri), name, duration, playedTime);
mPlayList.add(item);
}
cursor.close();
}
}
之後在需要的時候,直接將mPlayList
返回就可以了,
public class MusicService extends Service {
public class MusicServiceIBinder extends Binder {
......
public List<MusicItem> getPlayList() {
return mPlayList;
}
}
}
5.3 主介面播放列表的新增
MusicListActivity
有兩種方式新增播放列表:
單擊音樂項,將單首音樂新增到播放列表中;
長按音樂項,介面切換成
ListView
的多選模式,將多首音樂用替換掉方式新增到播放器當中;
這裡我們先來實現單擊音樂項的新增,多選模式我們放到後面單獨的章節來介紹。
修改點選列表的監聽器,通過MusicService提供的介面,把要新增的音樂交給MusicService處理,
//修改監聽器
private AdapterView.OnItemClickListener mOnMusicItemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MusicItem item = mMusicList.get(position);
if(mMusicService != null) {
//通過MusicService提供的介面,把要新增的音樂交給MusicService處理
mMusicService.addPlayList(mMusicList.get(position));
}
}
};
接下來開始實現顯示播放列表的功能,給MusicListActivity
做一個Menu選單,定義選單的xml檔案main_menu.xml
,
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:apps="http://schemas.android.com/apk/res-auto">
<item
android:title="@string/play_list"
apps:showAsAction="always"
android:icon="@mipmap/ic_playlist"
android:id="@+id/play_list_menu"/>
</menu>
將選單新增到MusicListActivity
當中,
public class MusicListActivity extends AppCompatActivity {
......
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
}
當用戶點選該選單的時候,彈出一個自帶列表的對話方塊,將播放列表顯示出來,
public class MusicListActivity extends AppCompatActivity {
......
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.play_list_menu: {
//響應使用者對選單的點選,顯示播放列表
showPlayList();
}
break;
}
return true;
}
private void showPlayList() {
final AlertDialog.Builder builder=new AlertDialog.Builder(this);
//設定對話方塊的圖示
builder.setIcon(R.mipmap.ic_playlist);
//設計對話方塊的顯示標題
builder.setTitle(R.string.play_list);
//獲取播放列表,把播放列表中歌曲的名字取出組成新的列表
List<MusicItem> playList = mMusicService.getPlayList();
ArrayList<String> data = new ArrayList<String>();
for(MusicItem music : playList) {
data.add(music.name);
}
if(data.size() > 0) {
//播放列表有曲目,顯示音樂的名稱
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
builder.setAdapter(adapter, null);
}
else {
//播放列表沒有曲目,顯示沒有音樂
builder.setMessage(getString(R.string.no_song));
}
//設定該對話方塊是可以自動取消的,例如當用戶在空白處隨便點選一下,對話方塊就會關閉消失
builder.setCancelable(true);
//建立並顯示對話方塊
builder.create().show();
}
}
/*******************************************************************/
* 版權宣告
* 本教程只在CSDN和安豆網釋出,其他網站出現本教程均屬侵權。
*另外,我們還推出了Arduino智慧硬體相關的教程,您可以在我們的網店跟我學Arduino程式設計中購買相關硬體。同時也感謝大家對我們這些碼農的支援。
*最後再次感謝各位讀者對安豆
的支援,謝謝:)
/*******************************************************************/