Android數據持久化存儲方式

Android系統中主要提供了三種方式用於簡單的實現數據持久化功能:

文件存儲(手機自帶的內存)SharedPreferences存儲以及數據庫存儲, 當然還可以用sd卡存儲

1,文件存儲

特點:手機自帶的內存,只能供當前應用程序訪問,其他應用程序訪問不了,程序卸載這些數據也會隨着消失

原理:
基本是先獲取一個文件的輸出流,然後把信息write進去,最後關閉流
a,通過上下文類context的openFileOutput()方法獲得一個FileOutputStream輸出流
b,要寫入的內容通過write()寫到FileOutputStream對象
c,關閉流
openFileOutput()可以將數據存儲到指定的文件中,方法有兩個參數,第一個參數是文件名,不需要帶上完整的路徑,因爲這裏都是默認存儲到data/data/file下面的

第二個參數是文件的操作模式,兩種:MODE_PRIVATE和MODE_APPEND.前者是覆蓋,後者是追加
(MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,前者是允許只讀,後者是隻寫,但是都被拋棄,因爲不安全)
[java] view plain copy
  1. private void save(String inputText ) {  
  2.            FileOutputStream fos = null;  
  3.            BufferedWriter writer = null;  
  4.             try {  
  5.                fos = openFileOutput( "data", Context.MODE_PRIVATE);  
  6.                writer = new BufferedWriter( new OutputStreamWriter(fos));  
  7.                 writer.write( inputText);  
  8.            } catch (IOException e) {  
  9.                  // TODO Auto-generated catch block  
  10.                  e.printStackTrace();  
  11.            } finally {  
  12.                  try {  
  13.                       if( writer != null)  
  14.                             writer.close();  
  15.                 }catch (IOException e) {  
  16.                       // TODO Auto-generated catch block  
  17.                       e.printStackTrace();  
  18.                 }  

主要的就是上面的三句話
openFileOutput打開一個輸出流,然後構建一個字節緩衝流對象然後寫數據,

此外還有幾個方法需要特別注意一下 ,這幾個方法對於文件關係提供了更好的支持,配合上面介紹的方式, 就可以對文件的數據進行常規的CRUD操作 (增刪改查),方法如下:
File getFIlesDir ():獲取文件系統的絕對路徑。
boolean deleteFile(String name):刪除一個指定文件名爲name的文件。
String[] fileList() :當前應用內部存儲路徑下的所有文件名。

[java] view plain copy
  1.  //幫助我們返回一個目錄  
  2.   //context.getCacheDir ()的話就是保存到cache緩存文件夾下面       
  3. File file=new File(context.getFilesDir(), "userinfo.txt");             
  4.        FileOutputStream fos= new FileOutputStream( file);            
  5.             //zhangsan 123  
  6.             fos.write(( username+ "##"+ password).getBytes());  
  7.             fos.close();  



2、sharedpreference 存儲(一般用於保存用戶設置偏好);

特點如下:

@1以鍵值對的形式保存到data/data/應用程序包名/shared_prefs目錄的XXX.xml文件中

@2目前支持的數據類型有String int float boolean long

@3不支持自定義的Object

@4通常用來存儲App上的用戶配置信息.如:是否震動,是否打開背景音樂 小遊戲積分 用戶賬號密碼信息

@5 在一些需要緩存的頁面數據的情況在,比如一個首頁的列表數據,在不需要對列表數據進行增刪改的情況下(一般app的頁面數據緩存僅需要查詢功能),可以取巧使用sp來保存json數據,再利用fastjson,gson等格式化工具來恢復數據。


要使用該方法來存儲數據就要先獲得一個SharedPreferences對象,有三種獲取方法
a,Context上下文類中的getSharedPreferences
兩個參數,第一個是指定文件的名稱,不在就創建。目錄也是在data/data/包名/shared_prefs目錄下
第二個參數是操作模式。MODE_PRIVATE是默認的,只允許當前的應用程序對其進行操作,MODE_MULTI_PROCESS是一般用於有多個進程中對同一個SharedPreferences文件進行讀寫的情況,同樣有MODE_WORLD_WRITEABLE MODE_WORLD_READABLE兩個被廢棄的模式
b,Activity類中的getPreferences
只有一個參數,也是操作模式,文件的名稱是默認的當前活動的類名
c,PreferenceManager管理類中的getDefaultSharedPreferences()
管理類中的一個靜態方法,接收一個context參數,自動把當前的包名作爲文件命名的前綴

得到一個對象之後,有三步來進行數據的存儲
1,調用對象的edit方法獲得一個SharedPreferences.Editor對象
2,向.Editor對象添加數據,putBoolean()或者是putString(),,等等putXXX()方法
3,調用commit方法將添加的數據提交,完成數據的存儲操作

例子:
[java] view plain copy
  1. @Override  
  2. public void onClick(View v) {  
  3.       // TODO Auto-generated method stub  
  4.  SharedPreferences.Editor editor=getSharedPreferences( "data", MODE_PRIVATE).edit();  
  5.              editor.putString( "name""HuaAn");  
  6.              editor.putInt( "id"9527);  
  7.              editor.putBoolean( "婚否"false );  
  8.              editor.commit();          
  9.            }  
  10.      });  

最後的結果是以xml的方式存在內存中的


從SharedPreferences中讀取數據 SharedPreferences提供了許多的get方法來進行獲取數據,都和相應的put方法對應
get方法也是有兩個參數,第一個“鍵”,第二個是鍵找不到值時候的默認值,自己設定把
還是繼續取出上面存儲的xml數據文件的數據 
[java] view plain copy
  1. restore_button .setOnClickListener(new OnClickListener() {             
  2.             @Override  
  3.             public void onClick(View v) {  
  4.                  // TODO Auto-generated method stub  
  5.    SharedPreferences  pref=getSharedPreferences( "data", MODE_PRIVATE);  
  6.              
  7.            String name= pref.getString( "name""HuaAn");  
  8.             int id= pref.getInt( "id"9527);  
  9.             boolean married= pref.getBoolean( "婚否"false ); 
  10.            }  
  11.      });  
  12.      }  


3 ,SQLite數據庫存儲

爲方便管理數據庫有一個專門的抽象類SQLiteOpenHelper,它有兩個抽象的方法onCreate()和onUpdate()
此外還有兩個實例方法,getReadableDatabase()和getWritableDatabase(),都可以創建或者是打開一個現有的數據庫(存在就打開,不在就創建),返回一個可對數據庫進行操作的對象
當數據庫不可寫入的時候,前者返回的是一個只能讀的方式打開數據庫,後者則會出現異常

數據庫文件同樣還是會放在data/data/包名/databases下面

實現步驟如下:

1,構建SQLiteOpenHelper的實例,也就是完成其構造函數(參數一是context,第二個是要創建的數據庫的名字,第三個是cursor,一般是null,第四個是數據庫的版本號)
2,再調用getReadableDatabase()或者getWritableDatabase()方法創建數據庫
同時重寫onCreate()方法,該方法也會得到執行
例子:

[java] view plain copy
  1. public class MyDatabaseHelper extends SQLiteOpenHelper {  
  2. /* 
  3. 補充一下建表的一些類型 
  4. integer ---整型 
  5. real-----浮點類型 
  6. text---文本類型 
  7. blob---二進制類型 
  8.  
  9. */  
  10. public static final String CREATE_BOOK= "create table book(id integer primary key autoincrement,"  
  11.            + "author text"  
  12.            + "price real"  
  13.            + "pages integer"  
  14.            + "name text)";   
  15.      private Context mContext ;  
  16.   
  17.      public MyDatabaseHelper(Context context, String name,  
  18.                 CursorFactory factory, int version) {  
  19.             super( context, name, factory, version);  
  20.             // TODO Auto-generated constructor stub  
  21.             mContext= context;  
  22.      }  
  23.   
  24.      @Override  
  25.      public void onCreate(SQLiteDatabase db) {  
  26.             // TODO Auto-generated method stub  
  27. //執行建表語句  
  28.     db.execSQL(CREATE_BOOK);  
  29.     Toast.makeText(mContext , "數據庫創建成功" , Toast.LENGTH_SHORT).show();  
  30.      }  
  31.   
  32.      @Override  
  33.      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  34.             // TODO Auto-generated method stub  
  35.      }  
  36. }  

  1. dbHelper= new MyDatabaseHelper( this"BookStore.db"null1);  
  2.      Button createDatabase=(Button) findViewById(R.id.create_database );  
  3.      createDatabase.setOnClickListener( new OnClickListener() {  
  4.              
  5.             @Override  
  6.             public void onClick(View v) {  
  7.                  // TODO Auto-generated method stub  
  8.                  dbHelper. getWritableDatabase();  
  9.            }  
  10.      });  

public long insert (String table, String nullColumnHack, ContentValues values)

Added in API level 1

Convenience method for inserting a row into the database.

Parameters
table the table to insert the row into
nullColumnHack optional; may be null. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided values is empty, no column names are known and an empty row can't be inserted. If not set to null, thenullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where your values is empty.
values this map contains the initial column values for the row. The keys should be the column names and the values the column values
Returns
  • the row ID of the newly inserted row, or -1 if an error occurred
[java] view plain copy
  1. Button addData =(Button) findViewById(R.id. add_data);  
  2.       addData.setOnClickListener( new OnClickListener() {           
  3.             @Override  
  4.             public void onClick(View v) {  
  5.                  // TODO Auto-generated method stub  
  6.                 SQLiteDatabase dbOperate= dbHelper.getWritableDatabase();  
  7.                 ContentValues values= new ContentValues();  
  8.             //下面沒有給表中的id賦值,因爲在建表的時候,id是默認自動增長的  
  9.                  //添加第一條記錄到Book  
  10.                  values.put( "name""安卓入門之路" );  
  11.                  values.put( "author""hl174");  
  12.                  values.put( "pages"800);  
  13.                  values.put( "price"50);                 
  14.                  dbOperate.insert( "book"null, values);  
  15.                   
  16.                  values.clear();  
  17.                   
  18.                  //插入第二條記錄到book  
  19.                  values.put( "name""安卓精通" );  
  20.                  values.put( "author""hl174");  
  21.                  values.put( "pages"700);  
  22.                  values.put( "price"45);       
  23.               dbOperate.insert( "book"null, values);  
  24.            }  
  25.      });  

更新數據:
update():四個參數

public int update (String table, ContentValues values, String whereClause, String[]whereArgs)

Added in API level 1

Convenience method for updating rows in the database.

Parameters
table the table to update in
values a map from column names to new column values. null is a valid value that will be translated to NULL.
whereClause the optional WHERE clause to apply when updating. Passing null will update all rows.
whereArgs You may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.
Retu rns
  • the number of rows affected
第一個參數:表名  第二個參數:ContentValues對象,
最後兩個參數是用來約束更新某一行或幾行中的數據,不指定的話就是更新所有行
[java] view plain copy
  1. //更新數據  
  2.      Button updateData=(Button) findViewById(R.id. update_data);  
  3.       updateData.setOnClickListener( new OnClickListener() {  
  4.             @Override  
  5.             public void onClick(View v) {  
  6.                  // TODO Auto-generated method stub  
  7.                 SQLiteDatabase db= dbHelper.getWritableDatabase();  
  8.                 ContentValues values= new ContentValues();  
  9.                  values.put( "price"10000);  
  10.                   
  11.         db.update( "book", values, "name=?"new String[]{"安卓入門之路" });  
  12.            }  
  13.      });  
上面第三個參數對應的是類似sql中的where語句,?是一個佔位符,第四個參數的內容可以替換掉該佔位符



刪除數據
很明顯,刪除數據就是delete()方法了

public int delete (String table, String whereClause, String[] whereArgs)

Added in API level 1

Convenience method for deleting rows in the database.

Parameters
table the table to delete from
whereClause the optional WHERE clause to apply when deleting. Passing null will delete all rows.
whereArgs You may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.
Returns
  • the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause.
三個參數:第一個是表名
第二個第三個同樣是進行約束的條件行
[java] view plain copy
  1. //刪除數據  
  2.      Button deleteData=(Button) findViewById(R.id. delete_data);  
  3.       deleteData.setOnClickListener( new OnClickListener() {        
  4.             @Override  
  5.             public void onClick(View v) {  
  6.                  // TODO Auto-generated method stub  
  7.                 SQLiteDatabase db= dbHelper.getWritableDatabase();  
  8.                  //刪除頁數大於500的記錄  
  9.                  db.delete( "book""pages>?"new String[]{"500" });  
  10.            }  
  11.      });  



查詢語句
CRUD中其實用的最多的還是查詢語句
同樣SQLiteDatabase也提供了query()方法,但是這個方法有好多個參數的類型,看最少的參數爲7個

public Cursor query (String table, String[] columns, String selection, String[]selectionArgs, String groupBy, String having, String orderBy)

Added in API level 1

Query the given table, returning a Cursor over the result set.

Parameters
table The table name to compile the query against.
columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
Returns
  • Cursor object, which is positioned before the first entry. Note that Cursors are not synchronized, see the documentation for more details.
See Also
1:表名
2:要查詢的是哪幾列,不指定的話就是默認查詢所有列
3、4:約束某一行或者是某幾行的數據,不指定則默認是查詢所有的數據
5,groupby指定的列,不指定這項參數就相當於跳過
6,having是對group之後的數據進行過濾
7可以指定查詢結果的排序方式

當然調用query之後會返回一個Cursor對象,查詢到的數據都將從這個對象中取出
[java] view plain copy
  1. public void onClick(View v ) {  
  2.           // TODO Auto-generated method stub  
  3.        SQLiteDatabase db= dbHelper.getWritableDatabase();  
  4.         //查詢book表中的所有數據  
  5.  Cursor cursor=  db.query( "book"nullnullnullnullnullnull);  
  6.    if( cursor.moveToFirst()){  
  7.           do{  
  8.              //遍歷cursor對象,取出數據並打印  
  9.          String name= cursor.getString( cursor.getColumnIndex( "name"));  
  10.        String author= cursor.getString( cursor.getColumnIndex( "author"));  
  11.      int pages= cursor.getInt( cursor.getColumnIndex( "pages"));  
  12.      double price= cursor.getDouble( cursor.getColumnIndex( "price"));  
  13.                              
  14.          Log. d("MainActivity" , "書名是:" +name );  
  15.          Log. d("MainActivity" , "書的作者是:" +author );  
  16.          Log. d("MainActivity" ,"書的頁數是:" +pages );  
  17.          Log. d("MainActivity" , "書的價錢是:" +price );  
  18.           } while( cursor.moveToNext());  
  19.          }  
  20.      cursor.close();  
  21.     }  
  22.   });  
首先是通過db.query得到cursor對象,在cursor類中我們發現了下面的一些方法,getString,getDouble,getInt等但是都需要傳一個參數進去,也就是所在列的下標,從0開始計數
要得到相應列所在的下標同樣有方法getColumnIndex(String columnName),這樣的話先得到列所在的下標,然後通過該下標得到相應的記錄值



public abstract int getColumnIndex (String columnName)

Added in API level 1

Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use getColumnIndexOrThrow(String) instead, which will make the error more clear.

Parameters
columnName the name of the target column.
Returns
  • the zero-based column index for the given column name, or -1 if the column name does not exist.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章