【android】音乐播放器之数据存储总结
? ? ? ??功能介紹如下:?? ?
? ? ? ??1、獲取本地歌曲列表,實現(xiàn)歌曲播放功能。?
? ? ? ? 2、利用jsoup解析網(wǎng)頁數(shù)據(jù),從網(wǎng)絡(luò)獲取歌曲列表,同時實現(xiàn)歌曲和歌詞下載到手機本地的功能。?
? ? ? ? 3、通知欄提醒,實現(xiàn)仿QQ音樂播放器的通知欄功能.?? ? ?
? ? ???涉及的技術(shù)有:?
? ? ? ?1、jsoup解析網(wǎng)絡(luò)網(wǎng)頁,從而獲取需要的數(shù)據(jù)?
? ? ? ?2、android中訪問網(wǎng)絡(luò),獲取文件到本地的網(wǎng)絡(luò)請求技術(shù),以及下載文件到本地實現(xiàn)斷點下載?
? ? ? ?3、線程池?
? ? ? ?4、圖片緩存?
? ? ? ?5、service一直在后臺運行?
? ? ? ?6、Activity與Fragment間的切換以及通信?
? ? ? ?7、notification通知欄設(shè)計?
? ? ? ?8、自定義廣播?
? ? ? ?9、android系統(tǒng)文件管
? ? ? ?音樂播放器思路及源碼下載見:【android】音樂播放器之設(shè)計思路
? ? ? 這篇文章主要來談?wù)刟ndroid數(shù)據(jù)存儲以及音樂播放器用到的一些存儲技術(shù)和緩存技術(shù)。當然小編也還是會順帶擴展下音樂播放器用到的其他方方面面的知識如果可能的話~!~!!!哈哈哈。先來總結(jié)寫目前android目前主要的5中數(shù)據(jù)存儲方式吧。
數(shù)據(jù)存儲方式
Android 的數(shù)據(jù)存儲有5種方式:
1. SharedPreferences存儲數(shù)據(jù)?
SharedPreferences數(shù)據(jù)存儲,也叫作xml存儲。這是將數(shù)據(jù)存儲“data/data/程序包名/share_prefs”路徑下的到xml文件中。 ??
2. 文件存儲數(shù)據(jù)?
分為內(nèi)部儲存和外部存儲。內(nèi)部存儲是應(yīng)用程序使用Android為自己分配的內(nèi)存空間,數(shù)據(jù)存儲到“/data/data/程序包名/files”路徑下的相應(yīng)文件中。外部存儲是使用手機sdcard的內(nèi)存(這個sdcard并不是我們經(jīng)常說的那個可以拆卸替換的SD卡,那個SD卡我們稱之為擴展卡),使用這部分內(nèi)存要聲明相應(yīng)的權(quán)限。?
3. SQLite數(shù)據(jù)庫存儲數(shù)據(jù)?
使用數(shù)據(jù)庫進行存儲,這個一般數(shù)據(jù)量比較大的時候。 ??
4. 使用ContentProvider存儲數(shù)據(jù)?
這個比較眼熟,ContentProvider也是Android的四大組件之一。ContentProvider一般是第三方提供的數(shù)據(jù)存儲方式,向我們手機中的通訊錄聯(lián)系人,照片,音樂等……?
5. 網(wǎng)絡(luò)存儲數(shù)據(jù)?
這個是將數(shù)據(jù)上傳到網(wǎng)絡(luò)上進行存儲。?
? ? ?下面就具體的看看每種存儲方式,先看看sharepreferences存儲技術(shù):
SharedPreferences存儲數(shù)據(jù)
SharedPreferences是一種輕型的數(shù)據(jù)存儲方式,實際上是基于XML文件存儲的“key-value”鍵值對數(shù)據(jù)。通常用來存儲程序的一些配置信息。其存儲在“data/data/程序包名/shared_prefs“目錄下。?
?
使用SharedPreferences來存儲數(shù)據(jù)首相我們要獲得SharedPreferences的對象。
獲得SharedPreferences的對象
獲得SharedPreferences對象的方法有三種:?
(1)通過Context的getSharedPrerences(key, [模式])方法獲取SharedPreferences對象;方法的第一個參數(shù)是用于指定SharedPreferences文件的名稱,第二個參數(shù)是指定操作模式,主要有兩種模式進行選擇:MODE_PRIVATE,?MODE_MULTI_PROCESS。默認操作是MODE_PRIVATE。除此之外還有MODE_EORLD_READEABLE,MODE_WORLD_WRITEABLE兩種。?
(2)通過Activity類提供的getPrerences(key)方法獲取到SharedPreferences對象;該方法會創(chuàng)建一個以當前活動類名作為SharedPreferences文件名的文件。?
(3)通過PreferencesManager類中的getDefaultPreferernces()方法獲得;這是一個靜態(tài)的方法,他接受一個Context參數(shù),并將當前應(yīng)用程序的包名作為SharedPreferences文件名。
下面我們來看一下如何使用SharedPreferences讀寫數(shù)據(jù)……
寫數(shù)據(jù)
步驟:
(1)根據(jù)Context的getSharedPrerences(key, [模式])方法獲取SharedPreferences對象;?
(2)利用SharedPreferences的editor()方法獲取Editor對象;?
(3)通過Editor的putXXX()方法,將鍵值對存儲數(shù)據(jù);?
(4)通過Editor的commit()方法將數(shù)據(jù)提交到SharedPreferences內(nèi)。
讀數(shù)據(jù)
步驟:
(1)根據(jù)Context的getSharedPrerences(key, [模式])方法獲取SharedPreference對象;?
(2)通過SharedPreference對象的getXXX方法獲得數(shù)據(jù)。例如:getString(String s, String s1)方法有兩個位參數(shù),第一個s為要獲得的值的鍵,第二個s1為如果鍵值不存在返回的默認的String類型的值。
文件存儲數(shù)據(jù)
文件存儲是Android中最基本的一種存儲方式,他不對存儲的內(nèi)容進行任何格式化的處理,所有的數(shù)據(jù)都是原封不動的保存在文件中的,因此他比較適合于存儲一些簡單的二進制數(shù)據(jù)或文本數(shù)據(jù)。?
文件存儲也分兩種:內(nèi)部存儲和外部存儲。?
內(nèi)部存儲
指Android為應(yīng)用程序分配的內(nèi)存。?
通過Context類中封裝好的輸入流和輸出流的獲取方法獲得數(shù)據(jù)/data/data//files目錄下存儲的數(shù)據(jù)。
files目錄下寫數(shù)據(jù)
通過Context的封裝好的方法?openFileOutput(String filename, int mode)獲得數(shù)據(jù)流:?
? ? ? ?String filename參數(shù):在/data/data//files目錄下存儲時的文件名。?
? ? ? ?int mode參數(shù):文件的操作模式,主要有兩種模式可選擇:MODE_PRIVATE,?MODE_APPEND。默認為MODE_PRIVATE,當指定相同文件名進行讀寫的時候,新的內(nèi)容會覆蓋原有內(nèi)容;MODE_APPEND模式會在已存在的文件的最后追加新的內(nèi)容。(還得多嘮叨嘮叨~!~)除此之外有兩種模式:MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE,這兩種模式表示允許其他應(yīng)用程序?qū)ξ覀兊某绦蛭募M行讀寫操作。
files目錄下讀數(shù)據(jù)
通過Context的封裝好的方法?openFileInput(String filename)獲得數(shù)據(jù)流:?
? ? ? ? ? ?String filename參數(shù):在/data/data//files目錄下讀取時的文件名。
外部存儲
? ? ? ? ? 對于多數(shù)情況下每個用戶都有自己的努力存儲空間,應(yīng)用僅對當前用戶的外部存儲空間有訪問權(quán)限:WRITE_EXTERNAL_STORAGE為對外部存儲空間的寫權(quán)限;READ_EXTERNAL_STORAGE為對外部存儲空間的寫權(quán)限;這些都需要在AndroidManifest.fex文件夾中聲明。
? ? ? ? ?READ_EXTERNAL_STORAGE:用于獲取主要的外部存儲目錄,當然這個目錄當前很有可能不能訪問,這就需要通過狀態(tài)判斷getExternalStorageState?
? ? ? ? ?getExternalStorageState:可以被用于獲取當前的狀態(tài);
? ? ? ? ?getExternalFileDir:返回的是應(yīng)用所在的目錄,當應(yīng)用被卸載后系統(tǒng)清理的就是這個目錄
? ? ? ? ?getExternalCacheDir:用于返回應(yīng)用外部的緩存目錄
SQLite數(shù)據(jù)庫存儲數(shù)據(jù)
? ? ? ?SQLite是一個輕量級關(guān)系型數(shù)據(jù)庫,既然是關(guān)系型數(shù)據(jù)庫,那操作起來其實跟mysql、sql server差不多的。?
? ? ? ?SQLite 和其他數(shù)據(jù)庫最大的不同就是對數(shù)據(jù)類型的支持,創(chuàng)建一個表時,可以在 CREATE TABLE 語句中指定某列的數(shù)據(jù)類型,但是你可以把任何數(shù)據(jù)類型放入任何列中。當某個值插入數(shù)據(jù)庫時,SQLite 將檢查它的類型。如果該類型與關(guān)聯(lián)的列不匹配,則 SQLite 會嘗試將該值轉(zhuǎn)換成該列的類型。如果不能轉(zhuǎn)換,則該值將作為其本身具有的類型存儲。比如可以把一個字符串(String)放入 INTEGER 列。SQLite 稱這為“弱類型”(manifest typing.)。?
對數(shù)據(jù)庫SQLite進行操作,我們要借助于SQLiteOpenHelper類進行操作。對數(shù)據(jù)庫的操作也就是”增、刪、改、查“。在學習數(shù)據(jù)庫的操作之前我們首先要學會如何創(chuàng)建數(shù)據(jù)庫……
創(chuàng)建數(shù)據(jù)庫
數(shù)據(jù)庫的操作借助于SQLiteOpenHelper,SQLiteOpenHelper是一個抽象類,我們我們在使用SQLiteOpenHelper時要先創(chuàng)建一個MySQLiteOpenHelper繼承SQLiteOpenHelper類。?
SQLiteOpenHelper有兩個非常重要的方法:getReadableDatabase()方法返回數(shù)據(jù)庫是一個只讀的;getWriteableDatabase()方法獲得是一個可讀寫的數(shù)據(jù)庫對象。這里我們使用getWriteableDatabase()方法獲得數(shù)據(jù)庫Database對象。?
添加數(shù)據(jù)
使用SQLiteDatabase的insert(String table, String nullColumnHack, ContentValues values)方法插入數(shù)據(jù)。這個方法包含三個參數(shù):?
我們先列舉一條SQLite中的插入語句:INSERT INTO user (name, passwords)] VALUES ("張三", "123456");?
String table:操作的數(shù)據(jù)表的名稱。?
String nullColumnHack:用于我們在未指定添加數(shù)據(jù)的情況下,為數(shù)據(jù)表中可以添加null值的數(shù)據(jù)填入null值。一般這個參數(shù)我們傳入null。?
ContentValues values:用于傳遞數(shù)據(jù),通常我們通過ContentValues 類的對象的putXXX()方法封裝數(shù)據(jù),然后將數(shù)據(jù)添加進數(shù)據(jù)庫。?
ContentValues 類,類似于java中的Map,以鍵值對的方式保存數(shù)據(jù)。
刪除數(shù)據(jù)
使用SQLiteDatabase的delete(String table, String whereClause, String[] whereArgs)方法刪除數(shù)據(jù)。這個方法包含三個參數(shù):?
我們先列舉一條SQLite中的刪除語句:DELETE FROM user WHERE name="張三"。?
String table:操作的數(shù)據(jù)表的名稱。?
String whereClause:約束刪除行的條件。相當于SQLite語句中“where name=?“內(nèi)容。?
String[] whereArgs:與前一個參數(shù)對應(yīng)約束刪除行的條件。相當于”where name=”張三““中的”張三“。?
注意:如果參數(shù)String whereClause和參數(shù)String[] whereArgs都傳null的話,就是刪除所有行。
修改數(shù)據(jù)
使用SQLiteDatabase的 update (String table, ContentValues values, String whereClause, String[] whereArgs)方法刪除數(shù)據(jù)。這個方法包含四個參數(shù):?
我們先列舉一條SQLite中的修改語句:UPDATE user SET name= "李四", passwords= "123" WHERE name="張三"。?
String table:操作的數(shù)據(jù)表的名稱。?
ContentValues values:用于傳遞數(shù)據(jù),通常我們通過ContentValues 類的對象的putXXX()方法封裝數(shù)據(jù),然后將數(shù)據(jù)添加進數(shù)據(jù)庫。?
String whereClause:約束修改行的條件。相當于SQLite語句中“where name=?“內(nèi)容。?
String[] whereArgs:與前一個參數(shù)對應(yīng)約束刪除行的條件。相當于”where name=”張三““中的”張三“。
查詢數(shù)據(jù)
對于”查“操作,SQLiteDatabase提供了多種方法。?
我們先列舉一條SQLite中的修改語句:SELECT passwords="123" FROM user。?
(1)使用SQL語句進行查詢。這里SQLiteDatabase提供了方法:
- rawQuery (String sql, String[] selectionArgs):該方法返回 Cursor類的對象,用于操作查詢的結(jié)果。
(2)使用SQLiteDatabase內(nèi)定方法查詢:
- query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit):這個方法有N多個參數(shù)啊……String table是操作的數(shù)據(jù)表的名稱;String selection是篩選的字段選項;String[] selectionArgs是字段選項對應(yīng)的值;String groupBy是篩選結(jié)果的分組依據(jù);String having是在由groupBy子句創(chuàng)建的分組上設(shè)置條件;String orderBy是結(jié)果的排序方式,String limit是篩選結(jié)果的顯示限制,例如“2, 3”是指從篩選結(jié)果的第2個開始顯示3個。
ContentProvider存儲數(shù)據(jù)
? ? ? ? ContentProvider內(nèi)容提供器,主要用于在不同應(yīng)用程序之間實現(xiàn)數(shù)據(jù)的共享功能。舉例來說,我們開發(fā)一個應(yīng)用程序,我們不可能只使用自己的數(shù)據(jù),也會用到其他應(yīng)用的數(shù)據(jù),像手機中的通訊錄聯(lián)系人,圖片,音樂等是使用到最多的。我們使用的SharedPreferences,文件存儲以及數(shù)據(jù)庫SQLite都是從存儲的應(yīng)用內(nèi)部的數(shù)據(jù),實現(xiàn)不同應(yīng)用間的數(shù)據(jù)共享就要使用到ContentProvider。?
ContentProvider使用方法有兩種:一種是使用現(xiàn)有的內(nèi)容提供器來讀取和操作相應(yīng)程序中的數(shù)據(jù);另一種是創(chuàng)建自己的內(nèi)容提供器給我們的應(yīng)用提供外部訪問接口。?
?
這里我們只講解使用已有的內(nèi)容提供器來讀取和操作相應(yīng)程序的數(shù)據(jù)。
ContentResolver的使用
想要訪問內(nèi)容提供器中的內(nèi)容我們需要借助ContentResolver類。?
ContentResolver為我們提供了”增“insert(Uri url, ContentValues values),“刪”delete(Uri url, String where, String[] selectionArgs),“改”update(Uri uri, ContentValues values, String where, String[] selectionArgs),“查”query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)方法對內(nèi)容提供器中的內(nèi)容進行操作,是不是很眼熟,對啊,和SQLiteDatabase中的增刪改查操作是一樣的,在此我們不再具體描述。
ContentResolver的使用
想要訪問內(nèi)容提供器中的內(nèi)容我們需要借助ContentResolver類。?
ContentResolver為我們提供了”增“insert(Uri url, ContentValues values),“刪”delete(Uri url, String where, String[] selectionArgs),“改”update(Uri uri, ContentValues values, String where, String[] selectionArgs),“查”query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)方法對內(nèi)容提供器中的內(nèi)容進行操作,是不是很眼熟,對啊,和SQLiteDatabase中的增刪改查操作是一樣的,在此我們不再具體描述。
Uri的使用
在SQLiteDatabase中,對數(shù)據(jù)庫的操作是通過接受數(shù)據(jù)庫的表名進行操作的,而在ContentResolver中是不接受表名的,而接受Uri對象。通過Uri指定操作的內(nèi)容“位置”。?
Uri由兩部分組成:權(quán)限和路徑。權(quán)限是對于不同的應(yīng)用程序進行區(qū)分的,一般用應(yīng)用程序的包名;路徑是對于同一應(yīng)用程序的不同表進行區(qū)分的。例如,我們有一個應(yīng)用程序的包名是“com.example.ontentproviderdemo”,應(yīng)用程序中有一個表“table”,則Uri為:“content://com.example.ontentproviderdemo/table”。
查詢通訊錄
我們以查詢通訊錄中的內(nèi)容為例,看一下ContentProvider的使用。通過Android提供的ContentProvider內(nèi)容提供器訪問通訊錄中的聯(lián)系人數(shù)據(jù)。?
1. 讀取聯(lián)系人是需要權(quán)限的,首先在AndroidManifext中加入權(quán)限
3. 創(chuàng)建一個Uri對象,指定訪問通訊錄。這里我們使用Android已經(jīng)解析好的Uri即可:ContactsContract.CommonDataKinds.Phone.CONTENT_URI ?
4. 查找聯(lián)系人內(nèi)容使用ContentResolver的query()方法,返回一個Cursor對象。
? ? ? 音樂播放器主要用到了文件存儲技術(shù)、sharepreferences存儲技術(shù)以及LruCache緩存技術(shù),當然如果你感興趣也可以自己玩玩數(shù)據(jù)庫啥的~!~
? ? 在PlayService啟動階段,會初始化本地音樂列表(見 【android】音樂播放器之service服務(wù)設(shè)計)通過MusicUtils訪問外部存儲設(shè)備sdcard讀取本地音樂:
public class MusicUtils {// 存放歌曲列表public static ArrayList<Music> sMusicList = new ArrayList<Music>();public static void initMusicList() {// 獲取歌曲列表sMusicList.clear();sMusicList.addAll(LocalMusicUtils.queryMusic(getBaseDir()));}/*** 獲取內(nèi)存卡根* @return*/public static String getBaseDir() {String dir = null;if (!Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)) {dir = Environment.getExternalStorageDirectory() + File.separator;} else {dir = App.sContext.getFilesDir() + File.separator;}return dir;}/*** 獲取應(yīng)用程序使用的本地目錄* @return*/public static String getAppLocalDir() {String dir = null;if (!Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)) {dir = Environment.getExternalStorageDirectory() + File.separator+ "Music" + File.separator;} else {dir = App.sContext.getFilesDir() + File.separator + "Music" + File.separator;}return mkdir(dir);}/*** 獲取音樂存放目錄* @return*/public static String getMusicDir() {String musicDir = getAppLocalDir();return mkdir(musicDir);}/*** 獲取歌詞存放目錄* * @return*/public static String getLrcDir() {String lrcDir = getAppLocalDir();return mkdir(lrcDir);}/*** 創(chuàng)建文件夾* @param dir* @return*/public static String mkdir(String dir) {File f = new File(dir);if (!f.exists()) {for (int i = 0; i < 5; i++) {if(f.mkdirs()) return dir;}return null;}return dir;} /*** 獲取目錄下的歌曲* @param dirName*/public static ArrayList<Music> queryMusic(String dirName) {ArrayList<Music> results = new ArrayList<Music>();Cursor cursor = App.sContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null,MediaStore.Audio.Media.DATA + " like ?",new String[] { dirName + "Music/" + "%" },MediaStore.Audio.Media.DEFAULT_SORT_ORDER);if(cursor == null) return results;// id title singer data time imageMusic music;for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {// 如果不是音樂String isMusic = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.IS_MUSIC));if (isMusic != null && isMusic.equals("")) continue;String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));if(isRepeat(title, artist)) continue;music = new Music();music.setId(cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)));music.setTitle(title.toString());music.setArtist(artist.toString());music.setUri(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)));music.setLength(cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)));music.setImage(getAlbumImage(cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID))));results.add(music);}cursor.close();return results;}? ? ?代碼非常的簡單,逐一的訪問sdcard讀取.mp3/.lrc文件,解析出歌名、著作填充到適配器中去。對于SharePreferences,我們知識將一些共享數(shù)據(jù)存儲在其中,比如每次播放歌曲在本地列表中的position等,部分代碼如下:
/*** 播放* @param position 音樂列表的位置* @return 當前播放的位置*/public int play(int position) {if(position < 0) position = 0;if(position >= MusicUtils.sMusicList.size()) position = MusicUtils.sMusicList.size() - 1;try {mPlayer.reset();mPlayer.setDataSource(MusicUtils.sMusicList.get(position).getUri());mPlayer.prepare();start();if(mListener != null) mListener.onChange(position);} catch (Exception e) {e.printStackTrace();}mPlayingPosition = position;SpUtils.put(Constants.PLAY_POS, mPlayingPosition);if(!readyNotification){startNotification();}else{setRemoteViews();}return mPlayingPosition;} public class SpUtils {public static void put(final String key, final Object value) {SharedPreferences sp = App.sContext.getSharedPreferences(Constants.SP_NAME, Context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();if(value instanceof Integer) {editor.putInt(key, (Integer) value);}else if(value instanceof Float) {editor.putFloat(key, (Float) value);}else if(value instanceof Boolean) {editor.putBoolean(key, (Boolean) value);}else if(value instanceof Long) {editor.putLong(key, (Long) value);}else {editor.putString(key, (String) value);}editor.commit();}public static Object get(Context context, String key, Object defaultObject) {SharedPreferences sp = App.sContext.getSharedPreferences(Constants.SP_NAME,Context.MODE_PRIVATE);if (defaultObject instanceof String) {return sp.getString(key, (String) defaultObject);} else if (defaultObject instanceof Integer) {return sp.getInt(key, (Integer) defaultObject);} else if (defaultObject instanceof Boolean) {return sp.getBoolean(key, (Boolean) defaultObject);} else if (defaultObject instanceof Float) {return sp.getFloat(key, (Float) defaultObject);} else if (defaultObject instanceof Long) {return sp.getLong(key, (Long) defaultObject);}return defaultObject;}/*** 移除某個key值已經(jīng)對應(yīng)的值* @param context* @param key*/public static void remove(Context context, String key) {SharedPreferences sp = context.getSharedPreferences(Constants.SP_NAME,Context.MODE_PRIVATE);sp.edit().remove(key).commit();}/*** 清除所有數(shù)據(jù)* @param context*/public static void clear(Context context) {SharedPreferences sp = context.getSharedPreferences(Constants.SP_NAME,Context.MODE_PRIVATE);sp.edit().clear().commit();} }? ? ?讀取本地音樂時,其中圖片顯示部分用到了圖片緩存技術(shù)MusicIconLoader類的實現(xiàn),在MusicIconLoader類中除調(diào)用 BitmapFactory提供的方法對圖片大小進行處理外(見Android高效加載大圖、多圖解決方案,有效避免程序OOM)還使用了LruCache緩存技術(shù),上面這篇文章講的很清楚,就直接看代碼吧:
? ? ?
public class MusicIconLoader { private static MusicIconLoader sInstance;private LruCache<String, Bitmap> mCache;// 獲取MusicIconLoader的實例public synchronized static MusicIconLoader getInstance() {if(sInstance == null) sInstance = new MusicIconLoader();return sInstance;}// 構(gòu)造方法, 初始化LruCacheprivate MusicIconLoader() {int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);mCache = new LruCache<String, Bitmap>(maxSize) {protected int sizeOf(String key, Bitmap value) { // return value.getByteCount();return value.getRowBytes() * value.getHeight();}};}// 根據(jù)路徑獲取圖片public Bitmap load(final String uri) {if(uri == null) return null;final String key = Encrypt.md5(uri);Bitmap bmp = getFromCache(key);if(bmp != null) return bmp;bmp = BitmapFactory.decodeFile(uri);addToCache(key, bmp);return bmp;}// 從內(nèi)存中獲取圖片private Bitmap getFromCache(final String key) {return mCache.get(key);}// 將圖片緩存到內(nèi)存中private void addToCache(final String key, final Bitmap bmp) {if(getFromCache(key) == null && key != null && bmp != null) mCache.put(key, bmp);} }
總結(jié)
以上是生活随笔為你收集整理的【android】音乐播放器之数据存储总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BeanShell遍历JSON双重嵌入数
- 下一篇: 举手无措......该怎么给视频配上好听