音乐播放器-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,数据产生了冗余,所以数据库设计还是很重要的。
相关文章推荐
- hdu 3572 Task Schedule(最大流)
- Java多线程(1)
- CSS规范-网易NEC
- Linux命令备忘实例(5)——切取命令
- Python爬虫教程——入门四之Urllib库的高级用法
- 我的算法学习之路
- 正则表达式
- CSS float小解
- webservice的简单理解
- [每月一题] 全排列的生成方法以及扩展问题
- Ununtu 15.04 安装MySql(Django连接Mysql)
- Clr Via C#读书笔记---CLR寄宿和应用程序域
- Clr Via C#读书笔记---程序集的加载和反射
- 20150830作业
- ubuntu下搭建samba服务,实现和window的文件共享
- 剑指offer:合并两个排序的链表 代码实现
- Python爬虫教程——入门三之Urllib库的基本使用
- 新加载页面$(window).focus()无效问题的解决
- Emmet:html/css代码快速编写神器
- Clr Via C#读书笔记---垃圾回收机制