Android系統(tǒng)的五種數(shù)據(jù)存儲(chǔ)形式實(shí)例(一)
Android系統(tǒng)有五種數(shù)據(jù)存儲(chǔ)形式,分別是文件存儲(chǔ)、SP存儲(chǔ)、數(shù)據(jù)庫(kù)存儲(chǔ)、contentprovider 內(nèi)容提供者、網(wǎng)絡(luò)存儲(chǔ)。其中,前四個(gè)是本地存儲(chǔ)。存儲(chǔ)的類型包括簡(jiǎn)單文本、窗口狀態(tài)存儲(chǔ)、音頻視頻數(shù)據(jù)、XML注冊(cè)文件的各種數(shù)據(jù)。各種存儲(chǔ)形式的特點(diǎn)不盡相同,因此對(duì)于不同的數(shù)據(jù)類型有著固定的存儲(chǔ)形式,本文為演示方便給出的案例基本相同,都是是采用賬號(hào)登錄來(lái)演示數(shù)據(jù)存儲(chǔ),保存賬號(hào)和密碼信息,下次登錄時(shí)記住賬號(hào)和密碼。重在說(shuō)明各種存儲(chǔ)形式的原理。
文件存儲(chǔ):
以I/O流的形式把數(shù)據(jù)存入手機(jī)內(nèi)存或SD卡,可以存儲(chǔ)大數(shù)據(jù),如音樂(lè)、圖片或視頻等。對(duì)于手機(jī)內(nèi)存來(lái)說(shuō)系統(tǒng)會(huì)根據(jù)每個(gè)應(yīng)用的包名創(chuàng)建一個(gè)/data/data/包名/的文件夾,訪問(wèn)自己包名下的目錄是不需要權(quán)限的,并且 Android 已經(jīng)提供了非常簡(jiǎn)便的 API 可以直接去訪問(wèn)該文件夾。訪問(wèn)時(shí)可以用getFilesDir()和getCacheDir(),兩個(gè)的區(qū)別是系統(tǒng)會(huì)自動(dòng)清理后者中的內(nèi)容。
SD卡中的文件通常位于mnt/sdcard目錄下,不同生產(chǎn)商生產(chǎn)的手機(jī)這個(gè)路徑可能不同。操作sd卡的時(shí)通常要判斷下sd卡是否可用以及剩余空間是否足夠,因?yàn)椴糠质謾C(jī)的SD卡可卸載,SD卡處于非掛載狀態(tài)時(shí),無(wú)法進(jìn)行讀寫操作。另外一點(diǎn),對(duì)SD卡的讀取和寫入操作均需要相應(yīng)的權(quán)限,否則無(wú)法完成。獲取SD卡路徑的方法是Environment.getExternalStorageDirectory(),其余操作與文件存儲(chǔ)基本類似。
文件存儲(chǔ)位置:
SD卡存儲(chǔ)路徑:
數(shù)據(jù)存儲(chǔ)在手機(jī)內(nèi)存的實(shí)現(xiàn)方法:
package com.example.qqload; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import com.example.qqload_sp.R; import android.os.Bundle; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.TextUtils; import android.view.Menu; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_qq; private EditText et_password; private CheckBox cb_remenber; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_qq = (EditText) findViewById(R.id.et_qq); et_password = (EditText) findViewById(R.id.et_password); cb_remenber = (CheckBox) findViewById(R.id.cb_remenber); File file = new File(getFilesDir(), "info.txt"); // File file = new File(getCacheDir(), "info.txt"); 緩存中存放數(shù)據(jù) if (file.exists() && file.length() > 0) { try { FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader( fis)); String line = br.readLine(); String qq = line.split("##")[0]; String password = line.split("##")[1]; et_qq.setText(qq); et_password.setText(password); fis.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void login(View view) { String qq = et_qq.getText().toString().trim(); String password = et_password.getText().toString().trim(); if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) { Toast.makeText(this, "密碼或者用戶名不能為空", 0).show(); return; } if (cb_remenber.isChecked()) { File file = new File(getFilesDir(), "info.txt"); try { FileOutputStream fos = new FileOutputStream(file); fos.write((qq + "##" + password).getBytes()); fos.close(); Toast.makeText(MainActivity.this, "保存成功", 0).show(); } catch (Exception e) { Toast.makeText(MainActivity.this, "保存失敗", 0).show(); e.printStackTrace(); } } } }
數(shù)據(jù)存儲(chǔ)在SD卡中的實(shí)現(xiàn)方法:
package com.example.qqload; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.text.Format; import com.example.qqload_sp.R; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.TextUtils; import android.text.format.Formatter; import android.view.Menu; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_qq; private EditText et_password; private CheckBox cb_remenber; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_qq = (EditText) findViewById(R.id.et_qq); et_password = (EditText) findViewById(R.id.et_password); cb_remenber = (CheckBox) findViewById(R.id.cb_remenber); File file = new File(Environment.getExternalStorageDirectory(), "info.txt"); if (file.exists() && file.length() > 0) { try { FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader( fis)); String line = br.readLine(); String qq = line.split("##")[0]; String password = line.split("##")[1]; et_qq.setText(qq); et_password.setText(password); fis.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void login(View view) { String qq = et_qq.getText().toString().trim(); String password = et_password.getText().toString().trim(); if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) { Toast.makeText(this, "密碼或者用戶名不能為空", 0).show(); return; } if (cb_remenber.isChecked()) { File file = new File(Environment.getExternalStorageDirectory(), "info.txt"); //判斷SD卡是否掛載 if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ Toast.makeText(MainActivity.this, "SD卡不可用", 0).show(); return; } //判斷SD卡大小是否充足 long size = Environment.getExternalStorageDirectory().getFreeSpace(); String info = Formatter.formatFileSize(this, size); //此處存儲(chǔ)數(shù)據(jù)較小就不進(jìn)行判斷 Toast.makeText(this, "可用空間" + info, 0).show(); try { FileOutputStream fos = new FileOutputStream(file); fos.write((qq + "##" + password).getBytes()); fos.close(); Toast.makeText(MainActivity.this, "保存成功", 0).show(); } catch (Exception e) { Toast.makeText(MainActivity.this, "保存失敗", 0).show(); e.printStackTrace(); } } } }
SP存儲(chǔ):
SP存儲(chǔ)本質(zhì)上是一個(gè)XML文件,以鍵值對(duì)的形式存入手機(jī)內(nèi)存中。常用于存儲(chǔ)簡(jiǎn)單的參數(shù)設(shè)置,如登陸賬號(hào)密碼的存儲(chǔ),窗口功能狀態(tài)的存儲(chǔ)等,該存儲(chǔ)文件位于:data/data/包名/shared_prefs文件夾中。使用的時(shí)候,首先需要通過(guò)context.getSharedPrefrences(String name,int mode)獲取SharedPrefrences的實(shí)例對(duì)象,存儲(chǔ)數(shù)據(jù)時(shí),用SharedPrefrences的實(shí)例對(duì)象得到SharedPrefrences文件的編輯器,在編輯器中用putXxx()添加數(shù)據(jù),之后務(wù)必用commit提交數(shù)據(jù),否則無(wú)法獲取數(shù)據(jù)。取數(shù)據(jù)時(shí),直接用getXxx()方法。
sp存儲(chǔ)自動(dòng)生成xml文件,其的路徑如下:
sp存儲(chǔ)的實(shí)現(xiàn)方法:
package com.example.qqload; import com.example.qqload_sp.R; import android.os.Bundle; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.TextUtils; import android.view.Menu; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_qq; private EditText et_password; private CheckBox cb_remenber; private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_qq = (EditText) findViewById(R.id.et_qq); et_password = (EditText) findViewById(R.id.et_password); cb_remenber = (CheckBox) findViewById(R.id.cb_remenber); sp = this.getSharedPreferences("config", 0); String qq = sp.getString("qq",""); String password = sp.getString("password",""); et_qq.setText(qq); et_password.setText(password); } public void login(View view){ String qq = et_qq.getText().toString().trim(); String password = et_password.getText().toString().trim(); if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(password)){ Toast.makeText(this,"密碼或者用戶名不能為空",0).show(); return; } if(cb_remenber.isChecked()){ Editor edit = sp.edit(); edit.putString("qq",qq); edit.putString("password",password); edit.commit(); } } }
數(shù)據(jù)庫(kù)存儲(chǔ):
數(shù)據(jù)庫(kù)所有信息都存儲(chǔ)在單一文件內(nèi),占用內(nèi)存小,并且支持基本SQL語(yǔ)法,是項(xiàng)目中經(jīng)常被采用的一種數(shù)據(jù)存儲(chǔ)方式,通常用于存儲(chǔ)用戶信息等,例如在手機(jī)上做一個(gè)學(xué)生信息管理系統(tǒng)。SQLite 是一款內(nèi)置到移動(dòng)設(shè)備上的輕量型的數(shù)據(jù)庫(kù),SQLiteOpenHelper 是Android 提供的一個(gè)抽象工具類,負(fù)責(zé)管理數(shù)據(jù)庫(kù)的創(chuàng)建、升級(jí)工作。數(shù)據(jù)庫(kù)的路徑為:/data/data/應(yīng)用包名/databases/數(shù)據(jù)庫(kù)。如果想創(chuàng)建數(shù)據(jù)庫(kù),就需要自定義一個(gè)類繼承SQLiteOpenHelper,然后覆寫其中的抽象方法,指定數(shù)據(jù)庫(kù)名、版本號(hào)。在onCreate() 方法中通過(guò)執(zhí)行sql 語(yǔ)句實(shí)現(xiàn)表的創(chuàng)建。如果只是創(chuàng)建出來(lái)該類并不會(huì)真正的去創(chuàng)建數(shù)據(jù)庫(kù),而是需要通過(guò)執(zhí)行helper.getWritableDatabase()或者h(yuǎn)epler.getReadableDatabase()。另外想要對(duì)創(chuàng)建的數(shù)據(jù)庫(kù)進(jìn)行增刪改查的操作可以單獨(dú)定義一個(gè)類實(shí)現(xiàn)。增刪改查操作有兩種方式,一是直接執(zhí)行sql語(yǔ)句,另一個(gè)是Android自身的API實(shí)現(xiàn)。用數(shù)據(jù)庫(kù)實(shí)現(xiàn)賬號(hào)登錄顯得有些大材小用,為演示數(shù)據(jù)庫(kù)的原理本文給出的案例是用數(shù)據(jù)庫(kù)記錄多個(gè)用戶的賬號(hào)和密碼信息,并把最后一個(gè)賬號(hào)信息回顯在界面。但實(shí)際應(yīng)用中很少這樣做。
從手機(jī)文件中導(dǎo)出數(shù)據(jù)庫(kù)文件并不可以直接打開(kāi),因此可以用可視化工具和sqlite3操作工具進(jìn)行查看。這里介紹sqlite3工具的使用。具體需要的步驟如下:
1. 執(zhí)行adb shell命令進(jìn)入Linuxne內(nèi)核;
2. 使用cd進(jìn)入數(shù)據(jù)庫(kù)所在的路徑 cd: /data/data/應(yīng)用包名/databases;
3. 進(jìn)入數(shù)據(jù)庫(kù)模式: sqlite3 數(shù)據(jù)庫(kù)名.db;
4. 執(zhí)行SQL語(yǔ)句
Sqlite3操作演示:
數(shù)據(jù)庫(kù)存儲(chǔ)路徑:
數(shù)據(jù)庫(kù)實(shí)現(xiàn)方法,先創(chuàng)建一個(gè)類繼承SqliteOpenHelper,在類中創(chuàng)建數(shù)據(jù)庫(kù)和表:
package com.example.qqload.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class UserDBOpenhelper extends SQLiteOpenHelper { public UserDBOpenhelper(Context context) { super(context, "user.db", null, 1); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase arg0) { arg0.execSQL("create table user (_id integer primary key autoincrement,name vachar(20),password varchar(20))"); } @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { // TODO Auto-generated method stub } }
創(chuàng)建一個(gè)工具類實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作:
package com.example.qqload.db.dao; 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.example.qqload.db.UserDBOpenhelper; public class UserDao { private UserDBOpenhelper helper; public UserDao(Context context){ helper = new UserDBOpenhelper(context); } public long add(String name,String password){ SQLiteDatabase db = helper.getWritableDatabase(); //用SQL語(yǔ)句實(shí)現(xiàn)增加數(shù)據(jù)的功能 //db.execSQL("insert into user (name,passeord) values (?,?)", new Object[]{name,password}); //android自身API實(shí)現(xiàn)修改功能可以有返回值 ContentValues values =new ContentValues(); values.put("name", name); values.put("password", password); long result = db.insert("user", null, values); //帶返回值,表示添加在哪一行 db.close(); return result; } public List<user> findAll(){ List<user> list =new ArrayList<user>(); SQLiteDatabase db = helper.getReadableDatabase(); //Cursor cursor = db.rawQuery("select name, password from user", null); Cursor cursor = db.query("user", new String[]{"name","password"}, null, null, null, null, null); while(cursor.moveToNext()){ String name = cursor.getString(0); String password = cursor.getString(1); user us = new user(); us.setName(name); us.setPassword(password); list.add(us); } cursor.close(); db.close(); return list; } }
在主方法中實(shí)現(xiàn)賬號(hào)登錄和記錄
package com.example.qqload; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.util.List; import com.example.qqload.db.dao.UserDao; import com.example.qqload.db.dao.user; import com.example.qqload.R; import android.os.Bundle; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.TextUtils; import android.view.Menu; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_qq; private EditText et_password; private CheckBox cb_remenber; private UserDao dao; private List<user> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_qq = (EditText) findViewById(R.id.et_qq); et_password = (EditText) findViewById(R.id.et_password); cb_remenber = (CheckBox) findViewById(R.id.cb_remenber); user u = new user(); dao = new UserDao(MainActivity.this); list = dao.findAll(); if (list.size() == 0) { et_qq.setText(""); et_password.setText(""); } else { System.out.println("大?。? + list.size()); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i).getName() + "::::" + list.get(i).getPassword()); } u = list.get(list.size()-1); String qq = u.getName(); String password = u.getPassword(); et_qq.setText(qq); et_password.setText(password); } } public void login(View view) { String qq = et_qq.getText().toString().trim(); String password = et_password.getText().toString().trim(); if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) { Toast.makeText(this, "密碼或者用戶名不能為空", 0).show(); return; } if (cb_remenber.isChecked()) { dao.add(qq, password); //在工具類添加增加功能 Toast.makeText(MainActivity.this, "保存成功", 0).show(); } } }
用數(shù)據(jù)庫(kù)實(shí)現(xiàn)賬號(hào)登錄案例的目錄結(jié)構(gòu)如下所示:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android開(kāi)發(fā)筆記之: 數(shù)據(jù)存儲(chǔ)方式詳解
- 在android開(kāi)發(fā)中進(jìn)行數(shù)據(jù)存儲(chǔ)與訪問(wèn)的多種方式介紹
- Android 數(shù)據(jù)存儲(chǔ)方式有哪幾種
- Android編程中的5種數(shù)據(jù)存儲(chǔ)方式
- Android平臺(tái)中實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)的5種方式
- Android數(shù)據(jù)存儲(chǔ)之SQLite使用
- 四種Android數(shù)據(jù)存儲(chǔ)方式
- android數(shù)據(jù)存儲(chǔ)之文件存儲(chǔ)方法
相關(guān)文章
Android 將網(wǎng)絡(luò)的Url資源轉(zhuǎn)換為Drawable資源方式
這篇文章主要介紹了Android 將網(wǎng)絡(luò)的Url資源轉(zhuǎn)換為Drawable資源方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Android中LeakCanary檢測(cè)內(nèi)存泄漏的方法
本篇文章主要介紹了Android中LeakCanary檢測(cè)內(nèi)存泄漏的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09Android SQLite數(shù)據(jù)庫(kù)進(jìn)行查詢優(yōu)化的方法
這篇文章主要給大家介紹了關(guān)于Android SQLite數(shù)據(jù)庫(kù)進(jìn)行查詢優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11Android studio利用gradle打jar包并混淆的方法詳解
昨天準(zhǔn)備把寫好的代碼使用gradle打jar包出來(lái),并打算加混淆。打jar包容易,結(jié)果在混淆上走了彎路。所以這篇文章主要介紹了關(guān)于Android studio利用gradle打jar包并混淆的方法,需要的朋友可以參考下。2017-03-03Android布局之RelativeLayout相對(duì)布局
RelativeLayout是相對(duì)布局控件:以控件之間相對(duì)位置或相對(duì)父容器位置進(jìn)行排列,下面通過(guò)本文給大家介紹Android布局之RelativeLayout相對(duì)布局,涉及到android relativelayout相對(duì)布局相關(guān)知識(shí),對(duì)android relativelayout相對(duì)布局相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧2015-12-12Android 中對(duì)于圖片的內(nèi)存優(yōu)化方法
Android 中對(duì)于圖片的內(nèi)存優(yōu)化方法,需要的朋友可以參考一下2013-03-03Android在項(xiàng)目中接入騰訊TBS瀏覽器WebView的教程與注意的地方
今天小編就為大家分享一篇關(guān)于Android在項(xiàng)目中接入騰訊TBS瀏覽器WebView的教程與注意的地方,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10Android組件化開(kāi)發(fā)路由的設(shè)計(jì)實(shí)踐
本篇文章主要介紹了Android組件化開(kāi)發(fā)路由的設(shè)計(jì)實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05Android 監(jiān)聽(tīng)屏幕是否鎖屏的實(shí)例代碼
今天小編通過(guò)本文給大家分享android如何監(jiān)聽(tīng)手機(jī)屏幕是否鎖屏。實(shí)現(xiàn)方法很簡(jiǎn)單,需要的朋友參考下吧2017-09-09