Android數據存儲

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();
                }
            }
        }
    }

執行效果

GIF.gif

外部存儲

外部存儲并非特指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);
GIF.gif

常用的緩存路徑

        Log.d("tag", "路徑1 " + this.getCacheDir());
        Log.d("tag", "路徑2 " + this.getExternalCacheDir());
        Log.d("tag", "路徑3 " + Environment.getDownloadCacheDirectory());
圖片.png

路徑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();
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容