SharedPreferences存儲
采用鍵值對的方式將數據存儲在一個XML文件中。
用途:主要用于保存應用內用戶的一些偏好設置,如應用的音量等等。
數據存儲過程
存數據
①獲取SharedPreferences對象,有三種方式:
/**
* 第一個參數為文件名稱
* 第二個參數為操作模式,常用的為MODE_PRIVATE,表示只有當前應用程序才可以對這個文件進行讀寫
*/
sharedPreferences = getSharedPreferences("test", MODE_PRIVATE);
/**
* 只接收一個操作模式參數
* 默認將當前活動的類名作為文件名
*/
sharedPreferences = getPreferences(MODE_PRIVATE);
/**
* 參數為上下文對象
* 使用當前應用程序的包名作為前綴來命名文件
*/
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
②調用SharedPreferences對象的edit()方法得到SharedPreferences.Editor對象
SharedPreferences.Editor editor = sharedPreferences.edit();
③向SharedPreferences.Editor對象采用鍵值對的形式添加數據
editor.putString("name", "shaw");
editor.putInt("age", 21);
editor.putBoolean("student", true);
前三步常用的寫法為:
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
④調用apply()方法提交數據
editor.apply();
取數據
①獲取SharedPreferences對象
②調用SharedPreferences對象的getString()、getInt()等方法讀取數據
/**
* 第一個參數為對應的鍵
* 第二個參數為找不到鍵對應的值時的默認返回值
*/
sharedPreferences.getString("name", "");
sharedPreferences.getInt("age", 0);
sharedPreferences.getBoolean("student", false);
文件存儲
內部存儲
內部存儲即存儲在應用程序內部,且文件默認是只能被當前應用所訪問的,當卸載應用的時候,對應的內部存儲的文件也會被刪除。SharedPreferences和SQLite數據庫都是存儲在內部存儲空間上的。
/**
* 保存內部存儲中的內容
* 內部存儲不需要聲明權限
* 使用openFileOutput來打開一個輸出流
*/
public void saveInner() {
FileOutputStream fos = null;
String input = inner_et.getText().toString();
try {
fos = openFileOutput("inner.txt", MODE_PRIVATE);
fos.write(input.getBytes());
Toast.makeText(this, "保存到內部存儲文件完成", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
//關閉流
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 讀取內部存儲中的內容
* 使用openFileInput來打開一個輸入流
*/
public void showInner() {
FileInputStream fis = null;
try {
fis = openFileInput("inner.txt");
int len = 0;
byte[] buf = new byte[1024];
//只要還沒讀到文件末尾就一直讀取
while ((len = fis.read(buf)) != -1) {
//將byte類型的數組轉換為String類型顯示
Toast.makeText(this, "讀取到了" + new String(buf, 0, len), Toast.LENGTH_SHORT).show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
執行效果
外部存儲
外部存儲并非特指sdcard,無論安卓手機上是否有可移動的sdcard,都存在著外部存儲空間,因為訪問可移動的sdcard或者手機的內置外部存儲都是通過相同的api。當手機連接電腦時,電腦可識別的部分一定為外部存儲空間。
使用外部存儲時要先檢驗存儲介質是否可用
//判斷當前sdcard是否可用
if (state.equals(Environment.MEDIA_MOUNTED)) {
Log.i("tag", "當前sdcard可用");
} else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
Log.i("tag", "當前sdcard只有讀取權限");
flag = false;
} else {
Log.i("tag", "當前sdcard不可用");
flag = false;
}
/**
* 使用外部存儲保存圖片
*/
public void saveImage() {
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
//獲取sdcard根路徑
File sdPath = Environment.getExternalStorageDirectory();
file = new File(sdPath, "test.jpg");
//讀取項目中的圖片資源
InputStream is = getResources().openRawResource(R.drawable.orange);
OutputStream os = new FileOutputStream(file);
//使用輸入輸出緩沖流進行讀寫操作
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(os);
int len = 0;
byte[] buf = new byte[1024];
while ((len = bis.read(buf)) != -1) {
//從0開始寫到len
bos.write(buf, 0, len);
//刷新操作
bos.flush();
}
Toast.makeText(this, "圖片寫入完成", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//關閉流操作
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 顯示圖片
*/
public void showImage() {
//從文件中讀取圖片
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());
out_image.setImageBitmap(bitmap);
}
對外部存儲的操作需要添加權限
<!--添加寫入權限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
若運行在Android6.0(API 23)及以上的系統中,需要添加動態權限處理
//申請向外部存儲寫數據的權限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
常用的緩存路徑
Log.d("tag", "路徑1 " + this.getCacheDir());
Log.d("tag", "路徑2 " + this.getExternalCacheDir());
Log.d("tag", "路徑3 " + Environment.getDownloadCacheDirectory());
路徑1為內部存儲緩存
路徑2位外部存儲緩存
路徑3為根目錄緩存
SQLite數據庫存儲
數據庫創建
繼承SQLiteOpenHelper類并重寫onCreate()和onUpgrade()方法
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
//數據庫被創建時執行,只執行一次
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeed", Toast.LENGTH_SHORT).show();
}
//數據庫版本更新時執行
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 第一個參數為context對象
* 第二個參數為數據庫名
* 第三個參數為一個自定義的Cursor對象,一般都為null
* 第四個參數為版本號
* 實例化該對象后使用構造方法創建數據庫
*/
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = (Button) findViewById(R.id.create_database);
Button addData = (Button) findViewById(R.id.add_data);
//創建數據庫
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//數據庫已存在則打開,否則創建
dbHelper.getWritableDatabase();
}
});
插入數據
/**
* 向表中添加數據
*/
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* getWritableDatabase()返回一個可對數據庫進行讀寫操作的對象,
* 當數據庫不可寫入時,將出現異常
*
* getReadableDatabase()返回一個可對數據庫進行讀寫操作的對象,
* 當數據庫不可寫入時,返回的對象以只讀的方式打開數據庫
*/
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
/**
* 開始裝填第一條數據
*/
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
更新數據
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book", values, "name=?", new String[]{"The Da Vinci Code"});
刪除數據
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages>?", new String[]{"500"});
查詢數據
SQLiteDatabase db = dbHelper.getWritableDatabase();
/**
* 第一個參數為表名
* 第二個參數指定查詢的列名
* 第三個參數指定where約束條件
* 第四個參數為where中的占位符提供具體的值
* 第五個參數指定需要group by的列
* 第六個參數對group by后的結果進一步約束
* 第七個參數指定查詢結果的排序方式,ASC由小到大,DESC由大到小
*/
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍歷Cursor對象
String name = cursor.getString(cursor.getColumnIndex("name"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
} while (cursor.moveToNext());
}
cursor.close();
也可以使用SQL語句完成CRUD操作
db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)", new String[]{
"The Da Vinci Code", "Dan Browm", "454", "16.96"
});
db.execSQL("update Book set price=? where name=?", new String[]{
"10.99", "The Da Vinci Code"
});
db.execSQL("delete from Book where pages>?", new String[]{"500"});
db.rawQuery("select * from Book", null);
即除了查詢操作使用rawQuery()方法外,其他操作均使用execSQL()方法完成。
Sqlite數據庫事務管理
為了保證數據庫中的某些操作要么同時執行,要么同時不執行,需要添加數據庫事務管理,
db.beginTransaction();
//具體的數據庫操作邏輯
db.setTransactionSuccessful();
db.endTransaction();