Android 五大存储方式具体解释
SharedPreferences與Editor
SharedPreferences保存的數(shù)據(jù)僅僅要是類似于配置信息格式的數(shù)據(jù)。因此它保存的數(shù)據(jù)主要是簡(jiǎn)單的key-value對(duì)形式。以下關(guān)系圖
上圖全然能夠看出,存的時(shí)候用SharedPreferences的內(nèi)部類Editor,取的時(shí)候用SharedPreferences。
SharedPreference是接口無(wú)法創(chuàng)建實(shí)例,Context提供以下方法創(chuàng)建實(shí)例 該實(shí)例僅僅能有一個(gè),也就是單例模式。
getSharedPreferences(String name,int mode);打開該文件看到
<?xml version="1.0" encoding="utf-8" standalone ="yes" ?> <map> <string name="name">value</string> </map>存儲(chǔ)的放值的時(shí)候String相應(yīng)XML文件中就是string節(jié)點(diǎn)。Int的時(shí)候相應(yīng)int節(jié)點(diǎn)。
存儲(chǔ)時(shí)長(zhǎng):卸載軟件時(shí)包名所在的目錄會(huì)消失,所以該文件無(wú)法相同會(huì)消失。
讀寫其它應(yīng)用的SharedPreferences
上述是在本身的APP中玩耍,這次看怎樣讀取其它應(yīng)用。關(guān)鍵是獲得其它應(yīng)用的程序的Context(代表Android應(yīng)用的全局信息的接口)又由于包名是Andoird應(yīng)用的唯一標(biāo)示,所以調(diào)用本APP的Context的方法
createPackageContext("android.example.homework", CONTEXT_IGNORE_SECURITY);得到其它應(yīng)用的Context對(duì)象而且其它應(yīng)用SharedPreferences是可讀狀態(tài)(可寫不行,必須可讀)后就能夠“為所欲為”了。 public class MainActivity extends Activity {SharedPreferences sp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 獲取SharedPreferences實(shí)例try {//通過(guò)包名得到該應(yīng)用的Context對(duì)象Context context=createPackageContext("com.example.homework", CONTEXT_IGNORE_SECURITY);//用其它應(yīng)用的Context創(chuàng)建SharedPreferencessp = context.getSharedPreferences("Test", Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);} catch (NameNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void btn(View view) {String string = sp.getString("name", "null");Toast.makeText(this, string, 1).show();} }
上述的讀寫并非唯一的,程序猿全然能夠利用IO流來(lái)直接操作本應(yīng)用和其它應(yīng)用的SharedPreferences數(shù)據(jù)。僅僅是Android將他封裝好了,非常簡(jiǎn)便。
無(wú)法存儲(chǔ)自己定義類型。主要存儲(chǔ)的APP配置信息,比如(username,password等)。
Chche存儲(chǔ)
存儲(chǔ)空間不夠系統(tǒng)會(huì)刪除Cache存儲(chǔ),但不要依賴系統(tǒng)刪除
存:
File dir = getCacheDir();File file = new File(dir,"test.txt");try {FileOutputStream fos = new FileOutputStream(file);fos.write("緩沖存儲(chǔ)".getBytes());} catch (Exception e) {// TODO: handle exception}取: FileInputStream fis = new FileInputStream(file)
以上兩種方式均為內(nèi)部存儲(chǔ),卸載應(yīng)用時(shí)數(shù)據(jù)都會(huì)丟失。
File存儲(chǔ)
FIle存儲(chǔ)就是Android繼續(xù)使用Java中的IO流繼續(xù)讀寫文件的一種方式
兩個(gè)核心方法:
openFileInput(String name);
openFIleOutput(String name);
以下是簡(jiǎn)單讀寫的樣例
public class MainActivity extends Activity {SharedPreferences sp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void readed(View view) {FileInputStream fis = null;StringBuffer sb=null;try {//打開文件輸入流 files文件名稱。這里系統(tǒng)不給加入后綴,不寫無(wú)后綴fis = openFileInput("files");byte[] buff = new byte[1024];int len = 0;sb = new StringBuffer();while ((len = fis.read(buff)) != -1) {sb.append(new String(buff, 0, len));}//關(guān)流fis.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}Toast.makeText(this, sb, 0).show();}public void writer(View view) {FileOutputStream fos = null;try {// 以追加模式打開文件輸出流fos = openFileOutput("files", MODE_APPEND);// 將流包裝成PrintStreamPrintStream printStream = new PrintStream(fos);printStream.print("內(nèi)容啦啦啦啦");Toast.makeText(this, "寫入成功", 0).show();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (fos != null)try {fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} }該文件無(wú)后綴,系統(tǒng)默認(rèn)不加入后綴。存放路徑為data/data/包名/file/目錄下
該文件依舊存放在包名下,所以卸載時(shí)依舊會(huì)丟失數(shù)據(jù)。
SD卡存儲(chǔ)
使用File存儲(chǔ)和SharedPreferences存儲(chǔ)的缺點(diǎn)是容量小,由于在應(yīng)用程序的數(shù)據(jù)目錄下。所以才有了SD卡存儲(chǔ)。使用SD卡存儲(chǔ)總共分為三步:
(1)推斷應(yīng)用是否有讀寫SD卡權(quán)限
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);(2)獲得SD卡的文件夾 File dir = Environment.getExternalStorageDirectory();(3)使用流讀寫數(shù)據(jù)SD卡的權(quán)限
<!-- 加入SD卡的創(chuàng)建與刪除文件權(quán)限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!-- 加入SD卡寫入權(quán)限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>讀寫SD卡樣例 public class MainActivity extends Activity {private final String FILE_NAME="test.txt";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}/**讀取數(shù)據(jù)*/public void readed(View view) {BufferedReader bis=null;//當(dāng)SD狀態(tài)裝備就緒時(shí)if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){File dir = Environment.getExternalStorageDirectory();try {File file = new File(dir, FILE_NAME);FileInputStream fis = new FileInputStream(file);//將fis流包裝成BufferedReaderbis= new BufferedReader(new InputStreamReader(fis));String len = null;StringBuffer sb = new StringBuffer("");while((len=bis.readLine())!=null){sb.append(len);}Toast.makeText(this, "讀到的數(shù)據(jù)是:"+sb, 0).show();} catch (Exception e) {e.printStackTrace();} finally{if(bis!=null){try {bis.close();} catch (IOException e) {e.printStackTrace();}}}}else Toast.makeText(this, "SD卡不可用", 0).show();}/**寫入數(shù)據(jù)*/public void writer(View view) {RandomAccessFile raf = null;if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){File dir = Environment.getExternalStorageDirectory();File file = new File(dir, FILE_NAME);//用指定文件創(chuàng)建RandomAccessFIletry {raf = new RandomAccessFile(file, "rw");//將文件記錄指針移動(dòng)到最后 防止再次寫入覆蓋之前的raf.seek(file.length()); raf.write("來(lái)一個(gè)字符串玩玩".getBytes());Toast.makeText(this, "寫入成功", 0).show();} catch (Exception e) {e.printStackTrace();}finally{if(raf!=null){try {raf.close();} catch (IOException e) {e.printStackTrace();}}}}} }
SQLite存儲(chǔ)
SQLite是輕量級(jí)的數(shù)據(jù)庫(kù)(底層就是一個(gè)數(shù)據(jù)庫(kù)文件)一旦應(yīng)用獲得了代表指定數(shù)據(jù)庫(kù)的SQLiteDatabase對(duì)象。接下來(lái)就能夠通過(guò)該對(duì)象來(lái)管理,操作數(shù)據(jù)庫(kù)了。
(1)獲取SQLiteDatabase對(duì)象。它代表了與數(shù)據(jù)庫(kù)的鏈接。
(2).調(diào)用SQLiteDatabase的方法來(lái)運(yùn)行SQL語(yǔ)句。
(3).操作SQL語(yǔ)句的運(yùn)行結(jié)果,比方用SimpleCursorAdapter封裝Cursor
(4).關(guān)閉SQLiDatabase。回收資源。
經(jīng)常用法
//創(chuàng)建(假設(shè)不存在)或打開數(shù)據(jù)庫(kù) static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory)//打卡一個(gè)已經(jīng)存在的數(shù)據(jù)庫(kù) static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags)MainActivity.java public class MainActivity extends Activity {private ListView listview;private SQLiteDatabase db;private EditText editText;private String TABLE_NAME="student";//創(chuàng)建表語(yǔ)句private String CREATE_TABLE = "create table "+TABLE_NAME+" (_id integer primary key autoincrement,name varchar(20),age integer)";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化editText = (EditText) findViewById(R.id.et);listview=(ListView) findViewById(R.id.listivew);//打開或創(chuàng)建數(shù)據(jù)庫(kù)(這里須要絕對(duì)路徑)db=SQLiteDatabase.openOrCreateDatabase("/mnt/sdcard/my.db3", null);if(!exits(TABLE_NAME)){db.execSQL(CREATE_TABLE);}}@Overrideprotected void onDestroy() {super.onDestroy();//關(guān)閉數(shù)據(jù)庫(kù)if(db!=null&&db.isOpen())db.close();}public void btn(View view){switch (view.getId()) {case R.id.btn1://插入String str = editText.getText().toString();String sql = "insert into "+TABLE_NAME+" (name) values ('"+str+"') ";System.out.println(sql);db.execSQL(sql);break;case R.id.btn2://讀取String sql2 = "select * from "+TABLE_NAME+"";Cursor cursor = db.rawQuery(sql2, null);inflateListView(cursor);break;}}public boolean exits(String table){String sql= "select * from sqlite_master where name="+"'"+table+"'";System.out.println(sql);Cursor cursor = db.rawQuery(sql, null);if(cursor.getCount()!=0){return true;}return false;}private void inflateListView(Cursor cursor){//構(gòu)建Cursor適配器的同一時(shí)候就是對(duì)Cursor封裝成為AdapterSimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{"name"}, new int[]{android.R.id.text1},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);listview.setAdapter(adapter);} }
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><EditTextandroid:id="@+id/et"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/btn1"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="btn"android:text="插入 字符串?dāng)?shù)據(jù)" /><Buttonandroid:id="@+id/btn2"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="btn"android:text="取出數(shù)據(jù)" /><ListViewandroid:id="@+id/listivew"android:layout_width="match_parent"android:layout_height="wrap_content" ></ListView></LinearLayout>
效果圖:
因?yàn)槭亲约憾x的路徑,所以卸載軟件依舊存在。這樣的直接使用SQLiteDatabase的方式使用的極少的。
注意:這里主鍵的列名必須為_id,由于SimpleCursorAdapter僅僅能識(shí)別列名為_id的主鍵。
android還為我們提供操作數(shù)據(jù)庫(kù)的一些便捷方法
insert方法
不管第三個(gè)參數(shù)是否有數(shù)據(jù),運(yùn)行該方法都會(huì)加入一條數(shù)據(jù)。
//table插入的表名//nullColumnHack強(qiáng)行插入為null列的列名 當(dāng)values參數(shù)為null或不包括隨意key-value對(duì)時(shí)該參數(shù)有效//values代表一行記錄的數(shù)據(jù)insert(String table, String nullColumnHack, ContentValues values)實(shí)際insert方法底層依舊通過(guò)SQL語(yǔ)句來(lái)插入的。由于它生成的SQL語(yǔ)句總是形如以下的語(yǔ)句 //ContentValue里的key-value對(duì)的數(shù)量決定了以下的key-value對(duì)。 insert into <表名>(key1,key2...)values(value1,value2....)假設(shè)此時(shí)第三個(gè)參數(shù)為空 insert into <表名>()values()該方法返回的數(shù)據(jù)庫(kù)影響的行數(shù)
//要更改數(shù)據(jù)庫(kù)表名 //更新完畢后的值 //滿足whereClaues字句的記錄將會(huì)被更新 //用于為whereClause字句傳入?yún)?shù) update(String table, ContentValues values, String whereClause, String[] whereArgs)比如我們想更新person表中的全部主鍵大于20的人的人名。可調(diào)用例如以下方法: ContentValues values = new ContentValues(); //存放更新之后的人名 values.put("name", "新人名");db.update("person", values, "_id>?", new Integer[]{20});
相應(yīng)SQL語(yǔ)句
updata person set key1=value1,key2=value2...where _id>20返回值更改的行數(shù)
//table表名。whereClause刪除的條件 。whereArgs給whereClause傳入刪除的參數(shù) delete(String table, String whereClause, String[] whereArgs)比如:想刪除person表中全部人名以王字開頭的記錄 db.delete("person","name like?",new String[]{"王%"});相應(yīng)SQl語(yǔ)句 delete person where name like '王%'query方法 //distinct指定是否去除反復(fù)記錄 //table 運(yùn)行查詢數(shù)據(jù)的表名 //columns要查詢出來(lái)的列名 //selection查詢條件的字句 相當(dāng)于select語(yǔ)句wherekeyword后面的部分。 //selectionArgs查詢語(yǔ)句匹配的參數(shù) //groupBy用于控制分組, //having 對(duì)分組進(jìn)行過(guò)濾 //orderBy 排序,personid desc降序,age asc升序; //limit 進(jìn)行分頁(yè) ?比如:5,10 db.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit, cancellationSignal);
SQLiteOpenHelper
這樣的繼承SQLiteOpenHelper方式用的還是比較多的。
它是Android提供的一個(gè)管理數(shù)據(jù)庫(kù)的工具類,可用于管理數(shù)據(jù)庫(kù)的創(chuàng)建的版本號(hào)和更新。
經(jīng)常用法:
synchronized SQLiteDatabase getReadableDatabase();以僅僅讀方式打開相應(yīng)SQLiteDatabase 對(duì)象
synchronized SQLiteDatabase getWritableDatabase();以寫方式打開相應(yīng)SQLiteDatabase 對(duì)象
abstract void Upgrade(SQLiteDatabase db,int oldVersion,int newVersion);當(dāng)數(shù)據(jù)庫(kù)版本號(hào)更新時(shí)回調(diào)該方法。
在獲得數(shù)據(jù)庫(kù)實(shí)例時(shí)建議使用getReadableDatabase();假設(shè)用getWritableDatabase()一旦磁盤滿了,打開數(shù)據(jù)庫(kù)就會(huì)出錯(cuò),而getReadableDatabase方法先僅僅讀方式打開,就算磁盤空間滿了,也不會(huì)出錯(cuò),而是繼續(xù)使用僅僅讀方式。
(getReadableDatabase調(diào)用時(shí)會(huì)包括getWritableDatabase)當(dāng)調(diào)用getReadableDatabase()假設(shè)數(shù)據(jù)庫(kù)不存在調(diào)用onCreate(SQLiteDatabase db);存在之后返回該實(shí)例
MyDB.java
MainActivity.java public class MainActivity extends Activity {String a;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyDB db = new MyDB(this, "mydb.db3", 1);SQLiteDatabase database = db.getReadableDatabase();} }
存儲(chǔ)路徑data/data/包名/databases/mydb.db3
卸載時(shí)文件依舊丟失。
查詢的時(shí)候會(huì)用到Cursor:
經(jīng)常用法:
isAfterLast()游標(biāo)的指針是否指向了最后一條數(shù)據(jù)的后面
moveToNext() 讓游標(biāo)的指針指向下一條數(shù)據(jù)
moveToFirst() 讓游標(biāo)的指針指向第一條數(shù)據(jù)
getString(int columnIndex) 獲取當(dāng)前行中指定列的String值。參數(shù)列索引
getColumnIndex(StringcolumnName) 依據(jù)列名字獲取列索引
插入會(huì)用到:ContentValus?
ContentValus的方法非常easy,鍵值對(duì)而已
改動(dòng)數(shù)據(jù):
//改動(dòng)?? 參數(shù)1:被改動(dòng)的表的名字?? 參數(shù)2:改動(dòng)的成為的值??? 參數(shù)3:更新條件?? 參數(shù)4:更新條件中占位符的值
db.update(DBHelper.TABLE_NAME, values,DBHelper.ENSCORE_NAME+" = ?", new String[]{"hanhan"});
?刪除數(shù)據(jù):
//數(shù)據(jù)刪除? 參數(shù)1:要?jiǎng)h除數(shù)據(jù)的表的名字?? 參數(shù)2:刪除條件??? 參數(shù)3:刪除條件中的占位符的值
? ? ? ? //返回值---》刪除數(shù)據(jù)的行數(shù)
db.delete(DBHelper.TABLE_NAME,DBHelper.ENSCORE_NAME+" = ?", new String[]{"zhangsan"})。
總結(jié)
以上是生活随笔為你收集整理的Android 五大存储方式具体解释的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: redis 3.x windows 集群
- 下一篇: select multiple=mul