Android_7_數(shù)據(jù)存數(shù)方式
使用SharedPreferences存儲數(shù)據(jù)
-
獲取SharedPreferences對象
調(diào)用Context對象的getSharedPreferences()方法
-
調(diào)用Activity對象的getPreferences()方
調(diào)用Context對象的getSharedPreferences()方法獲得的SharedPreferences對象可以被同一應(yīng)用程序下的其他組件共享. 調(diào)用Activity對象的getPreferences()方法獲得的SharedPreferences對象只能在該Activity中使用. Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問,在該模式下,寫入的內(nèi)容會覆蓋原文件的內(nèi)容 Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件. Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應(yīng)用是否有權(quán)限讀寫該文件. MODE_WORLD_READABLE:表示當前文件可以被其他應(yīng)用讀取. MODE_WORLD_WRITEABLE:表示當前文件可以被其他應(yīng)用寫入
-
SharedPreferences存儲數(shù)據(jù)
SharedPreferences只支持基本數(shù)據(jù)類型
public static boolean getBoolean(Context context, String key) { if (sp == null) { sp = context.getSharedPreferences(name, Context.MODE_PRIVATE); } return sp.getBoolean(key, false); }
封裝過的使用SharedPreferences存儲一個bool值對象,同理可以使用putInt,putString等方法保存其他類型的數(shù)據(jù)
文件存儲數(shù)據(jù)
文件存儲就是通過流的方式,把數(shù)據(jù)寫到文件中,使用Context,Environment獲得路徑
Context常用方法目錄:
方法:getFilesDir
釋義:返回通過Context.openFileOutput()創(chuàng)建和存儲的文件系統(tǒng)的絕對路徑围小,應(yīng)用程序文件偷拔,這些文件會在程序被卸載的時候全部刪掉愉舔。
/data/data/package_name/files
方法:getDir
釋義:這是一個可以存放你自己應(yīng)用程序自定義的文件笨使,你可以通過該方法返回的File實例來創(chuàng)建或者訪問這個目錄樱溉,注意該目錄下的文件只有你自己的程序可以訪問眯亦。
getDir("test", Context.MODE_WORLD_WRITEABLE)
/data/data/package_name/app_test
方法:getCacheDir
釋義:返回應(yīng)用程序指定的緩存目錄腰素,這些文件在設(shè)備內(nèi)存不足時會優(yōu)先被刪除掉芦倒,所以存放在這里的文件是沒有任何保障的蛤织,可能會隨時丟掉赴叹。
/data/data/package_name/cache
方法:getExternalFilesDir
釋義:使用這個方法需要寫外部存儲的權(quán)限“”,這個目錄是與應(yīng)用程序相關(guān)的外部文件系統(tǒng)指蚜,這些文件只屬于你的應(yīng)用乞巧,不能被其它人訪問。同樣姚炕,這個目錄下的文件在程序被卸載時也會被一同刪除摊欠。該方法也可以指定返回某一資源類型,這些類型可以是:
Environment#DIRECTORY_MUSIC 音樂
Environment#DIRECTORY_PODCASTS 音頻
Environment#DIRECTORY_RINGTONES 鈴聲
Environment#DIRECTORY_ALARMS 鬧鈴
Environment#DIRECTORY_NOTIFICATIONS 通知鈴聲
Environment#DIRECTORY_PICTURES 圖片
Environment#DIRECTORY_MOVIES 視頻
getExternalFilesDir( "/" )
/storage/sdcard0/Android/data/package_name/files
getExternalFilesDir( Environment.DIRECTORY_PICTURES )
/storage/sdcard0/Android/data/package_name/files/Pictures
方法:getExternalCacheDir
使用這個方法需要寫外部存儲的權(quán)限“”柱宦,調(diào)用該方法會返回應(yīng)用程序的外部文件系統(tǒng)(Environment.getExternalStorageDirectory())目錄的絕對路徑些椒,它是用來存放應(yīng)用的緩存文件,它和getCacheDir目錄一樣掸刊,目錄下的文件都會在程序被卸載的時候被清除掉免糕。
/storage/sdcard0/Android/data/package_name/cache
方法:getDatabasePath
釋義:保存通過Context.openOrCreateDatabase 創(chuàng)建的數(shù)據(jù)庫文件
getDatabasePath("DATABASE_NAME") )
/data/data/package_name/databases/DATABASE_NAME
方法:getPackageCodePath
釋義:返回android 安裝包的完整路徑,這個包是一個zip的壓縮文件,它包括應(yīng)用程序的代碼和assets文件石窑。
/data/app/package_name-2.apk
方法:getPackageResourcePath
釋義:返回android 安裝包的完整路徑牌芋,這個包是一個ZIP的要鎖文件,它包括應(yīng)用程序的私有資源松逊。
/data/app/package_name-2.apk
方法:getObbDir
釋義:返回應(yīng)用程序的OBB文件目錄(如果有的話)躺屁,注意如果該應(yīng)用程序沒有任何OBB文件,這個目錄是不存在的经宏。
/storage/sdcard0/Android/obb/package_name
Environment
Environment類去獲取外部存儲目錄犀暑,在訪問外部存儲之前一定要先判斷外部存儲是否已經(jīng)是可使用(已掛載&可使用)狀態(tài)。并且需要在AndroidManifest.xml文件中添加外部存儲讀和寫的權(quán)限烁兰。
Environment類中提供了幾個靜態(tài)常量用于標識外部存儲的狀態(tài)耐亏,這些狀態(tài)都是String類型
MEDIA_BAD_REMOVAL 在沒有掛載前存儲媒體已經(jīng)被移除。
MEDIA_CHECKING 正在檢查存儲媒體沪斟。
MEDIA_MOUNTED 存儲媒體已經(jīng)掛載广辰,并且掛載點可讀/寫。
MEDIA_MOUNTED_READ_ONLY 存儲媒體已經(jīng)掛載主之,掛載點只讀择吊。
MEDIA_NOFS 存儲媒體是空白或是不支持的文件系統(tǒng)。
MEDIA_REMOVED 存儲媒體被移除杀餐。
MEDIA_SHARED 存儲媒體正在通過USB共享干发。
MEDIA_UNMOUNTABLE 存儲媒體無法掛載朱巨。
MEDIA_UNMOUNTED 存儲媒體沒有掛載史翘。
可以通過靜態(tài)方法getExternalStorageState()來獲取外部存儲的狀態(tài),如果程序需要在外部存儲里面讀寫數(shù)據(jù)冀续,必須要先判斷琼讽。
SQLite數(shù)據(jù)庫存儲數(shù)據(jù)
SQLite是一款開源的、嵌入式關(guān)系型數(shù)據(jù)庫,沒有獨立運行的進程洪唐,與所服務(wù)的應(yīng)用程序在應(yīng)用程序 進程空間內(nèi)共生共存钻蹬。它的代碼與應(yīng)用程序代碼也是在一起的,或者說嵌入其中凭需,作為托管它的程序 的一部分问欠。因此不存在數(shù)據(jù)庫的客戶端和服務(wù)器,使用SQLite一般只需要帶上它的一個動態(tài)庫粒蜈,就可 以享受它的全部功能顺献。
-
SQLite支持的數(shù)據(jù)類型
SQLite采用動態(tài)數(shù)據(jù)存儲類型,會根據(jù)存入的值自動進行判斷枯怖。SQLite支持以下5種數(shù)據(jù)類型: ∽⒄(1)NULL:空值 (2)INTEGER:帶符號的整型 (3)REAL:浮點型 ≈坠臁(4)TEXT:字符串文本 ∈倜帷(5)BLOB:二進制對象
-
創(chuàng)建SQLite數(shù)據(jù)庫
創(chuàng)建類繼承自SQLiteOpenHelper,并復(fù)寫其onCreate(),onUpgrade(),onDeleteDB()方法,其中onCreate()方法會在創(chuàng)建數(shù)據(jù)庫后調(diào)用,在這里使用sql語句建表,在onUpgrade()方法中,是數(shù)據(jù)庫升級時對比版本對表或數(shù)據(jù)進行修改,onDeleteDb()是數(shù)據(jù)庫被刪除時回調(diào)的方法
public class AndroidSQLiteOpenHelper extends SQLiteOpenHelper { // 數(shù)據(jù)庫名稱 public static final String DBNAME = "android.db"; // 數(shù)據(jù)庫版本 public static final int VERSION = 2; // 建表語句,大小寫不敏感 private static final String CREATETABLE = "create table " + Person.TABLENAME + "(id string, name string, gender int, age int)"; public AndroidSQLiteOpenHelper(Context context) { super(context, DBNAME, null, VERSION); } // 創(chuàng)建表 @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATETABLE); } // 更新表 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { this.deleteDB(db); this.onCreate(db); } // 刪除表 private void deleteDB(SQLiteDatabase db) { db.execSQL("drop table if exists " + Person.TABLENAME); } }
-
使用SQLite中的數(shù)據(jù)
實例化上一步中定義的SQLiteOpenHelper子類對象,調(diào)用getWritableDatabase()方法可以獲得SQLiteDataBase對象,使用SQLiteDataBase對象就可以直接對數(shù)據(jù)庫進行操作了
public DatabaseManager(Context context) { dbHelper = new AndroidSQLiteOpenHelper(context); } // 插入記錄 public int insert(Person person) { Log.e("SQLite", "----insert----"); SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { db.execSQL("insert into " + Person.TABLENAME + " values(?, ?, ?, ?)", new Object[] { person.id, person.name, person.gender, person.age }); db.setTransactionSuccessful(); } catch (Exception e) { return 0; } finally { db.endTransaction(); } db.close(); return 1; } // 刪除記錄 public int delete(Person person) { Log.e("SQLite", "----delete----"); SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { db.execSQL("delete from " + Person.TABLENAME + " where id = ?", new Object[] { person.id }); db.setTransactionSuccessful(); } catch (Exception e) { return 0; } finally { db.endTransaction(); } db.close(); return 1; } // 更新記錄 public int update(Person person) { Log.e("SQLite", "----update----"); SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { db.execSQL("update " + Person.TABLENAME + " set name=?, gender=?, age=? where id=?", new Object[] { person.name, person.gender, person.age, person.id }); db.setTransactionSuccessful(); } catch (Exception e) { return 0; } finally { db.endTransaction(); } db.close(); return 1; } // 查詢記錄 public ArrayList<Person> query(String id) { Log.e("SQLite", "----query----"); SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor; Person person; ArrayList<Person> list = new ArrayList<Person>(); // 若fileId為null或""則查詢所有記錄 if (id == null || id.equals("")) { cursor = db.rawQuery("select * from " + Person.TABLENAME, null); } else { cursor = db.rawQuery("select * from " + Person.TABLENAME + " where id=?", new String[] { id }); } while (cursor.moveToNext()) { person = new Person(); person.id = cursor.getString(cursor.getColumnIndex("id")); person.name = cursor.getString(cursor.getColumnIndex("name")); person.gender = cursor.getString(cursor.getColumnIndex("gender")); person.age = cursor.getInt(cursor.getColumnIndex("age")); Log.e("SQLite", person.toString()); list.add(person); } cursor.close(); db.close(); if (list.size() == 0) { Log.e("SQLite", "****表中無數(shù)據(jù)****"); } return list; } }
網(wǎng)絡(luò)存儲數(shù)據(jù)
所謂網(wǎng)絡(luò)存儲就是把數(shù)據(jù)存儲到服務(wù)器上,這個過程需要使用網(wǎng)絡(luò)請求
使用ContentProvider存儲數(shù)據(jù)
-
ContentProvider作為Android四大組件之一,一般自己很少定義ContentProvider,現(xiàn)多用在訪問系統(tǒng)提供的數(shù)據(jù)上,ContentProvider可以實現(xiàn)在應(yīng)用程序之間共享數(shù)據(jù).
1椒袍、ContentProvider使用表的形式來組織數(shù)據(jù),無論數(shù)據(jù)的來源是什么驼唱,ContentProvider都會認為是一種表,然后把數(shù)據(jù)組織成表格 2驹暑、ContentProvider提供的方法 query:查詢 insert:插入 update:更新 delete:刪除 getType:得到數(shù)據(jù)類型 onCreate:創(chuàng)建數(shù)據(jù)時調(diào)用的回調(diào)函數(shù)
-
使用步驟
1曙蒸、 定義一個CONTENT_URI常量(里面的字符串必須是唯一)
Public static final Uri CONTENT_URI = Uri.parse("content://com.MyContentprovider"); 如果有子表,URI為: Public static final Uri CONTENT_URI = Uri.parse("content://com.MyContentProvider/users");
2岗钩、 定義一個類纽窟,繼承ContentProvider
Public class MyContentProvider extends ContentProvider
3、實現(xiàn)ContentProvider的所有方法(query兼吓、insert臂港、update、delete视搏、getType审孽、onCreate)
public class MyContentProvider extends ContentProvider { //訪問表的所有列 public static final int INCOMING_USER_COLLECTION = 1; //訪問單獨的列 public static final int INCOMING_USER_SINGLE = 2; //操作URI的類 public static final UriMatcher uriMatcher; //為UriMatcher添加自定義的URI static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user", INCOMING_USER_COLLECTION); uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#", INCOMING_USER_SINGLE); } private DatabaseHelp dh; //為數(shù)據(jù)庫表字段起別名 public static HashMap userProjectionMap; static { userProjectionMap = new HashMap(); userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID); userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME); } /** * 刪除表數(shù)據(jù) */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { System.out.println("delete"); //得到一個可寫的數(shù)據(jù)庫 SQLiteDatabase db = dh.getWritableDatabase(); //執(zhí)行刪除,得到刪除的行數(shù) int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs); return count; } /** * 數(shù)據(jù)庫訪問類型 */ @Override public String getType(Uri uri) { System.out.println("getType"); //根據(jù)用戶請求浑娜,得到數(shù)據(jù)類型 switch (uriMatcher.match(uri)) { case INCOMING_USER_COLLECTION: return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE; case INCOMING_USER_SINGLE: return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM; default: throw new IllegalArgumentException("UnKnown URI"+uri); } } /** * 插入數(shù)據(jù) */ @Override public Uri insert(Uri uri, ContentValues values) { //得到一個可寫的數(shù)據(jù)庫 SQLiteDatabase db = dh.getWritableDatabase(); //向指定的表插入數(shù)據(jù)佑力,得到返回的Id long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values); if(rowId > 0){//判斷插入是否執(zhí)行成功 //如果添加成功,利用新添加的Id和 Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId); //通知監(jiān)聽器筋遭,數(shù)據(jù)已經(jīng)改變 getContext().getContentResolver().notifyChange(insertedUserUri, null); return insertedUserUri; } return uri; } /** * 創(chuàng)建ContentProvider時調(diào)用的回調(diào)函數(shù) */ @Override public boolean onCreate() { System.out.println("onCreate"); //得到數(shù)據(jù)庫幫助類 dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME); return false; } /** * 查詢數(shù)據(jù)庫 */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //創(chuàng)建一個執(zhí)行查詢的Sqlite SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); //判斷用戶請求打颤,查詢所有還是單個 switch(uriMatcher.match(uri)){ case INCOMING_USER_COLLECTION: //設(shè)置要查詢的表名 qb.setTables(UserTableMetaData.TABLE_NAME); //設(shè)置表字段的別名 qb.setProjectionMap(userProjectionMap); break; case INCOMING_USER_SINGLE: qb.setTables(UserTableMetaData.TABLE_NAME); qb.setProjectionMap(userProjectionMap); //追加條件,getPathSegments()得到用戶請求的Uri地址截取的數(shù)組,get(1)得到去掉地址中/以后的第二個元素 qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1)); break; } //設(shè)置排序 String orderBy; if(TextUtils.isEmpty(sortOrder)){ orderBy = UserTableMetaData.DEFAULT_SORT_ORDER; } else{ orderBy = sortOrder; } //得到一個可讀的數(shù)據(jù)庫 SQLiteDatabase db = dh.getReadableDatabase(); //執(zhí)行查詢漓滔,把輸入傳入 Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); //設(shè)置監(jiān)聽 c.setNotificationUri(getContext().getContentResolver(), uri); return c; } /** * 更新數(shù)據(jù)庫 */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { System.out.println("update"); //得到一個可寫的數(shù)據(jù)庫 SQLiteDatabase db = dh.getWritableDatabase(); //執(zhí)行更新語句编饺,得到更新的條數(shù) int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs); return count; } }
4、在AndroidMinifest.xml中進行聲明
<provider
android:name=".cp.MyContentProvider"
android:authorities="com.cp.MyContentProvider"
android:exported="true" >
</provider>
- 這樣一個ContentProvider就定義完成了,可以在另一個程序使用ContentResolver進行在應(yīng)該間互相使用數(shù)據(jù)了