您的位置:首页 > 其它

音乐播放器-DAO

2015-09-05 00:22 537 查看
private static String[] proj_music = new String[] {
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ARTIST_ID,
MediaStore.Audio.Media.DURATION };


看整个app,核心数据就是这样传递的,

首先从MusicUtils查询看5个DAO是否有数据,如果没数据从系统的ContentResolver里面用系统的URI读取数据,并给4个DAO设置数据,

然后就可以以后从DAO里面读取数据了。。

先交代下MusicUtils

在MusicUtils里面数据库并没有存音乐的data,而是将其路径存储了

String filePath = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
/**
* 音频文件的路径存储在数据库里面而不是整个文件
*/
music.data = filePath;
String folderPath = filePath.substring(0,
filePath.lastIndexOf(File.separator));
music.folder = folderPath;


MusicUtils里面用到了pingyin4j工具,本工程将其封装成StringHelper

/**
* StringHelper.getPingyin得到汉字的拼音
*/
music.musicNameKey = StringHelper.getPingYin(music.musicName);
music.artistKey = StringHelper.getPingYin(music.artist);
musicList.add(music);

先看MusicUtils:

在queryMusic方法里面:

if (mMusicInfoDao.hasData()) {
return mMusicInfoDao.getMusicInfo();
} else {
List<MusicInfo> list = getMusicList(cr.query(uri, proj_music,
select.toString(), null,
MediaStore.Audio.Media.ARTIST_KEY));
mMusicInfoDao.saveMusicInfo(list);
return list;


也就是说,如果MusicDao里面已经有data的时候就从musicinfodao里面获取,如果没有的话就查询后放在list里面,在list返回之前,把musicinfo存在MusicInfoDao里面。

接下来看看MusicDao:

/**
* Copyright (c) www.longdw.com
*/
package com.ldw.music.db;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.ldw.music.activity.IConstants;
import com.ldw.music.model.MusicInfo;

public class MusicInfoDao implements IConstants {

private static final String TABLE_MUSIC = "music_info";
private Context mContext;

public MusicInfoDao(Context context) {
this.mContext = context;
}
/**
* 插入到数据库
* @param list
*/
public void saveMusicInfo(List<MusicInfo> list) {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
for (MusicInfo music : list) {
ContentValues cv = new ContentValues();
cv.put("songid", music.songId);
cv.put("albumid", music.albumId);
cv.put("duration", music.duration);
cv.put("musicname", music.musicName);
cv.put("artist", music.artist);
cv.put("data",music.data);
cv.put("folder", music.folder);
cv.put("musicnamekey", music.musicNameKey);
cv.put("artistkey", music.artistKey);
cv.put("favorite", music.favorite);
db.insert(TABLE_MUSIC, null, cv);
}
}
/**
* 调用{parseCursor}从数据库中查询得到List<MusicInfo>
* @return list
*/
public List<MusicInfo> getMusicInfo() {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
String sql = "select * from " + TABLE_MUSIC;

return parseCursor(db.rawQuery(sql, null));
}

private List<MusicInfo> parseCursor(Cursor cursor) {
List<MusicInfo> list = new ArrayList<MusicInfo>();
while(cursor.moveToNext()) {
MusicInfo music = new MusicInfo();
music._id = cursor.getInt(cursor.getColumnIndex("_id"));
music.songId = cursor.getInt(cursor.getColumnIndex("songid"));
music.albumId = cursor.getInt(cursor.getColumnIndex("albumid"));
music.duration = cursor.getInt(cursor.getColumnIndex("duration"));
music.musicName = cursor.getString(cursor.getColumnIndex("musicname"));
music.artist = cursor.getString(cursor.getColumnIndex("artist"));
music.data = cursor.getString(cursor.getColumnIndex("data"));
music.folder = cursor.getString(cursor.getColumnIndex("folder"));
music.musicNameKey = cursor.getString(cursor.getColumnIndex("musicnamekey"));
music.artistKey = cursor.getString(cursor.getColumnIndex("artistkey"));
music.favorite = cursor.getInt(cursor.getColumnIndex("favorite"));
list.add(music);
}
cursor.close();
return list;
}
/**
* MusicUtils里面会从不容的地方获取music,比如艺术家,唱片集等
* @param selection
* @param type
* @return
*/
public List<MusicInfo> getMusicInfoByType(String selection, int type) {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
String sql = "";
if(type == START_FROM_ARTIST) {
sql = "select * from " + TABLE_MUSIC + " where artist = ?";
} else if(type == START_FROM_ALBUM) {
sql = "select * from " + TABLE_MUSIC + " where albumid = ?";
} else if(type == START_FROM_FOLDER) {
sql = "select * from " + TABLE_MUSIC + " where folder = ?";
}
return parseCursor(db.rawQuery(sql, new String[]{ selection }));
}
/**
* 设置喜欢的状态,这个数是用是整数表示的
* @param id
* @param favorite
*/
public void setFavoriteStateById(int id, int favorite) {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
String sql = "update " + TABLE_MUSIC + " set favorite = " + favorite + " where _id = " + id;
db.execSQL(sql);
}

/**
* 数据库中是否有数据
* @return
*/
public boolean hasData() {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
String sql = "select count(*) from " + TABLE_MUSIC;
Cursor cursor = db.rawQuery(sql, null);
boolean has = false;
if(cursor.moveToFirst()) {
int count = cursor.getInt(0);//传入的是第0列,返回的是行的数目,如果为0列则没有
if(count > 0) {
has = true;
}
}
cursor.close();
return has;
}
/**
* 获取多少个音乐
* @return count
*/
public int getDataCount() {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
String sql = "select count(*) from " + TABLE_MUSIC;
Cursor cursor = db.rawQuery(sql, null);
int count = 0;
if(cursor.moveToFirst()) {
count = cursor.getInt(0);
}
return count;
}

}

我们发现这里面的代码并不多,主要的还是get和set方法,另外这里面有个比较关键的概念,跟这个项目息息相关,那就是数据库设计,我们先接着往下看,最后的数据库:

/**
* Copyright (c) www.longdw.com
*/
package com.ldw.music.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseHelper extends SQLiteOpenHelper {

private static SQLiteDatabase mDb;
private static DatabaseHelper mHelper;
private static final int DB_VERSION = 3;
private static final String DB_NAME = "musicstore_new";//数据库名字
/**下面是5个数据表
*/
private static final String TABLE_ALBUM = "album_info";
private static final String TABLE_ARTIST = "artist_info";
private static final String TABLE_MUSIC = "music_info";
private static final String TABLE_FOLDER = "folder_info";
private static final String TABLE_FAVORITE = "favorite_info";
//单例模式的应用,gof的23种模式是一个java程序员是否优秀的判别标准之一
public static SQLiteDatabase getInstance(Context context) {
if (mDb == null) {
mDb = getHelper(context).getWritableDatabase();
}
return mDb;
}

public static DatabaseHelper getHelper(Context context) {
if(mHelper == null) {
mHelper = new DatabaseHelper(context);
}
return mHelper;
}

public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
//这个方法并没有用到
public DatabaseHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table "
+ TABLE_MUSIC
+ " (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " songid integer, albumid integer, duration integer, musicname varchar(10), "
+ "artist char, data char, folder char, musicnamekey char, artistkey char, favorite integer)");
db.execSQL("create table "
+ TABLE_ALBUM
+ "(_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "album_name char, album_id integer, number_of_songs integer, album_art char)");
db.execSQL("create table "
+ TABLE_ARTIST
+ "(_id INTEGER PRIMARY KEY AUTOINCREMENT, artist_name char, number_of_tracks integer)");
db.execSQL("create table "
+ TABLE_FOLDER
+ "(_id INTEGER PRIMARY KEY AUTOINCREMENT, folder_name char, folder_path char)");
db.execSQL("create table "
+ TABLE_FAVORITE
+ " (_id integer,"
+ " songid integer, albumid integer, duration integer, musicname varchar(10), "
+ "artist char, data char, folder char, musicnamekey char, artistkey char, favorite integer)");
}
//数据更新
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ARTIST);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ALBUM);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MUSIC);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FOLDER);
onCreate(db);//我们有理由怀疑这种行为美意义,恰好没有version2,如果有的话也没意义,不过不影响程序运行
}
}
//并没有用到
public void deleteTables(Context context) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_ALBUM, null, null);
db.delete(TABLE_ARTIST, null, null);
db.delete(TABLE_FAVORITE, null, null);
db.delete(TABLE_FOLDER, null, null);
db.delete(TABLE_MUSIC, null, null);
}

}

好了,现在可以看下数据库设计了:

先扯下数据库的基本知识,sqlite的数据库要有_id(如果没有需要在select的时候as _id挺麻烦的),

数据库都是要有完整性约束的

比如primary key,通常_Id都要 自增且约束。

但是我们发现在MusicUtils里面Music查询信息只有9个(除了自增的id),并且查询后没有做修改就直接set给底层的DAO,于是数据库就浪费了1个:

db.execSQL("create table "
+ TABLE_MUSIC
+ " (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " songid integer, albumid integer, duration integer, musicname varchar(10), "
+ "artist char, data char, folder char, musicnamekey char, artistkey char, favorite integer)");
private static String[] proj_music = new String[] {
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ARTIST_ID,
MediaStore.Audio.Media.DURATION };//一共有7个并且在下面的方法中设置了9个,2个是转化来的
List<MusicInfo> list = getMusicList(cr.query(uri, proj_music,
select.toString(), null,
MediaStore.Audio.Media.ARTIST_KEY));
mMusicInfoDao.saveMusicInfo(list);

getMusicList()方法只有9个:

public static ArrayList<MusicInfo> getMusicList(Cursor cursor) {
if (cursor == null) {
return null;
}
ArrayList<MusicInfo> musicList = new ArrayList<MusicInfo>();
while (cursor.moveToNext()) {
MusicInfo music = new MusicInfo();
music.songId = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media._ID));
music.albumId = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
music.duration = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.DURATION));
music.musicName = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.TITLE));
music.artist = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST));

String filePath = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
/**
* 音频文件的路径存储在数据库里面而不是整个文件
*/
music.data = filePath;
String folderPath = filePath.substring(0,
filePath.lastIndexOf(File.separator));
music.folder = folderPath;
/** * StringHelper.getPingyin得到汉字的拼音 */ music.musicNameKey = StringHelper.getPingYin(music.musicName); music.artistKey = StringHelper.getPingYin(music.artist); musicList.add(music);
}
cursor.close();
return musicList;
}


设置函数saveMusicInfo:

public void saveMusicInfo(List<MusicInfo> list) {
SQLiteDatabase db = DatabaseHelper.getInstance(mContext);
for (MusicInfo music : list) {
ContentValues cv = new ContentValues();
cv.put("songid", music.songId);
cv.put("albumid", music.albumId);
cv.put("duration", music.duration);
cv.put("musicname", music.musicName);
cv.put("artist", music.artist);
cv.put("data",music.data);
cv.put("folder", music.folder);
cv.put("musicnamekey", music.musicNameKey);//最后的这3个其实都是空,
cv.put("artistkey", music.artistKey);
cv.put("favorite", music.favorite);
db.insert(TABLE_MUSIC, null, cv);
}
}

少了哪一个呢?少了favorate

中间的3个跳过,没什么问题

接下来看favorite表,11个项(包括_id,因为_id不是自增的),甚至可以说favorite直接就是music的复制品,只是music没有用favorite,数据产生了冗余,所以数据库设计还是很重要的。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: