Android數據持久化,你還不會?

嘚吧嘚

數據持久化是開發過程中不可避免的,因爲數據是核心,是非常重要的。

總結一下常用的數據持久化的方式:

  • SharedPreferences存儲數據
  • 文件存儲數據
  • SQLite數據庫存儲數據
  • ContentProvider存儲數據

話不多說,上乾貨。

SharedPreferences(共享首選項)

適用範圍:
保存少量的數據,且這些數據的格式非常簡單(基本數據類型)。比如應用程序的各種配置信息(如是否打開音效、是否使用震動效果、小遊戲的玩家積分等),解鎖口令密碼等
核心原理:
數據的保存形式是基於XML文件存儲的key-value鍵值對,通常用來存儲一些簡單的配置信息。通過DDMS的File Explorer面板,展開文件瀏覽樹,很明顯SharedPreferences數據總是存儲在/data/data//shared_prefs目錄下。SharedPreferences對象本身只能獲取數據而不支持存儲和修改,存儲和修改是通過SharedPreferences.edit()獲取的嵌入類Editor實現。

獲取首選項對象

SharedPreferences sp = getSharedPreferences(String name, int mode);

參數:
name: 首選項文件的名稱
mode: 首選項文件打開模式
   MODE_PRIVATE 只能在本應用程序讀寫
   MODE_WORLD_READABLE 能被其他應用讀
   MODE_WORLD_WRITEABLE 能被其他應用讀寫

通過嵌入類Editor寫數據

//獲取嵌入類Editor
SharedPreferences.Editor edit = sp.edit();
//寫數據
edit.putXXXX(String key, value);
//提交
edit.commit();

在這裏插入圖片描述
切記,切記,寫完數據之後一定要提交,否則首選項文件不會保存數據
來看一下官方開發文檔中的介紹:

在這裏插入圖片描述

簡單翻譯一下:
提交從編輯首選項對象的編輯器返回的首選項文件中的改變(大體就是這個意思,若是翻譯的不好,大佬勿噴🙈)


翻譯過來有點繞,斷一下句好理解一些了:
提交 / 從 / 編輯首選項對象的編輯器 / 返回的 / 首選項文件中的改變
不提交就不會保存數據的更改

從首選項文件獲取數據

SharedPreferences.getXXXX(String key, defaultvalue);

在這裏插入圖片描述

學以致用

layout佈局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="信息" />

</LinearLayout>

核心代碼:

/*
 * 獲得 共享首選項對象(p1:文件名,p2:讀寫模式)
 * 只有當前程序對test進行讀寫(test不存在時會自動創建)
 */
SharedPreferences sp = getSharedPreferences("test", MODE_PRIVATE);
/*
 * 寫數據,通過嵌套類Editor寫數據
 * 寫數據,保存在內存中沒有加入磁盤中
 */
SharedPreferences.Editor edit = sp.edit();
edit.putString("姓名", "張三");
edit.putInt("年齡", 21);
edit.putBoolean("性別", true);
//提交數據
edit.commit();

//讀取數據
String str = "姓名:" + sp.getString("姓名", "") +
             ",年齡:" + sp.getInt("年齡", 0) +
             ",性別:" + sp.getBoolean("性別", true);

Button msgBtn = findViewById(R.id.msg);
        msgBtn.setOnClickListener((v) -> {
            Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
        });

效果圖:

在這裏插入圖片描述

文件存儲數據(File Java I/O)

將數據寫入文件

核心代碼

FileOutputStream fos = openFileOutput(fileName, mode);
fos.write(message.getBytes());
fos.close();

參數:
fileName: 數據待寫入的文件名稱
mode:文件打開模式
   MODE_PRIVATE: 爲默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容,如果想把
            新寫入的內容追加到原文件中。可以使用MODE_APPEND
   MODE_APPEND: 模式會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件。
   MODE_WORLD_READABLE: 表示當前文件可以被其他應用讀取
   MODE_WORLD_WRITEABLE: 表示當前文件可以被其他應用寫入

從文件中讀出數據

核心代碼

//fileName爲待讀取數據的文件的名稱
FileInputStream inStream = openFileInput(fileName);
byte[] buffer = new byte[1024];
int len = 0;
StringBuilder sb = new StringBuilder();
//從文件中讀取數據
while ((len = inStream.read(buffer)) != -1) {
        sb.append(new String(buffer, 0, len));
}
//關閉輸入流
inStream.close();
//轉化爲字符串
str = sb.toString();

學以致用

在這裏插入圖片描述
首先將寫入數據和讀取數據的方法寫好。

    /**
     * 讀出文件中的數據
     *
     * @param fileName 文件的名稱
     * @return 讀出的數據
     */
    public String read(String fileName) {
        try {
            //創建一個FileInputStream對象
            FileInputStream inStream = openFileInput(fileName);
            byte[] buffer = new byte[1024];
            int len = 0;
            StringBuilder sb = new StringBuilder();
            //從文件中讀取數據
            while ((len = inStream.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }
            //關閉輸入流
            inStream.close();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 向文件中寫入數據
     *
     * @param message  待寫入的數據
     * @param fileName 文件名稱
     * @param mode     打開文件的模式
     */
    public void write(String message, String fileName, int mode) {
        //獲取輸入值
        if (message == null)
            return;
        try {
            //創建一個FileOutputStream對象,mode爲文件打開的模式
            FileOutputStream fos = openFileOutput(fileName, mode);
            //將獲取過來的值放入文件
            fos.write(message.getBytes());
            //關閉輸出流
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

layout佈局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="信息" />

    <Button
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="商店" />

</LinearLayout>

MainActivity主要代碼(實際開發中不能這麼寫,只作爲演示用)

write("籃球:10個\n排球:5個\n羽毛球:6個\n", "message.txt", MODE_PRIVATE);
Button info = findViewById(R.id.info);
info.setOnClickListener((v) -> {
    String read = read("message.txt");
    Toast.makeText(MainActivity.this, read, Toast.LENGTH_SHORT).show();
});

效果圖:

在這裏插入圖片描述

SQLite數據庫存儲數據

SQLite是輕量級嵌入式數據庫引擎,它支持SQL語言,並且只利用很少的內存就有很好的性能。在我們爲移動設備開發應用程序時,也許就要使用到SQLite,所以我們就需要掌握移動設備上的SQLite開發技巧。

使用SQLite數據庫需要自定義一個類繼承SQLiteOpenHelper幫助類來創建和升級數據庫。

在這裏插入圖片描述
提供一個簡單的模板,如下:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyHelper extends SQLiteOpenHelper {
    Context myContext;//上下文對象

    /**
     * @param context 上下文對象
     * @param name    數據庫名稱
     * @param factory 遊標工具類,用null
     * @param version 數據庫版本,整數
     */
    public MyHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        myContext = context;
    }

    //第一次創建數據庫時調用,如果數據庫已經存在,就不在調用
    @Override
    public void onCreate(SQLiteDatabase db) {
        //創建一個學生表吧
        String createTable = "create table student ("
                + "id integer primary key autoincrement,"
                + "sNumber text,"
                + "sName text,"
                + "sAge text)";

        db.execSQL(createTable);//創建數據庫表
        Toast.makeText(myContext, "學生表創建完畢!", Toast.LENGTH_LONG).show();
    }

    //數據庫版本變化時,會調用onUpgrade()
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //你的代碼
    }
}

使用數據庫類SQLiteDatabase對數據庫進行CRUD操作
僞代碼如下:

MyHelper helper = new MyHelper(MainActivity.this, "stud.db", null, 1);
SQLiteDatabase database = helper.getWritableDatabase();

//增 在數據庫例添加幾條數據
ContentValues values = new ContentValues();//ContentValue:封裝表中一行,用來添加或修改數據表
cv.put("sNumber","2018001");
cv.put("sName", "Tom");
cv.put("sAge", "21");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018002");
cv.put("sName", "Tom");
cv.put("sAge", "22");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018003");
cv.put("sName", "Tom");
cv.put("sAge", "19");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018004");
cv.put("sName", "Jack");
cv.put("sAge", "21");
database.insert("student", null, cv);
cv.clear();

//刪 刪除名字叫“Tom”,年齡爲22歲的數據
int delete = database.delete("student", "sName = ? and sAge = ?", new String[]{"Tom", "22"});
System.out.println("res = " + delete);

//改 修改名字叫“Tom”,年齡爲21歲的數據,把名字修改爲“Tom2”
values.put("sName", "Tom2");//修改的數據
int update = database.update("student", values, "SName = ? and sAge = ?", new String[]{"Tom", "21"});
cv.clear();
System.out.println("res = " + update);

//查 查詢所有數據
Cursor stu = database.query("student", null, null, null, null, null, null);//Cursor:遊標類,封裝查詢結果
if (stu.moveToFirst()) {
    do {
        String sNumber = stu.getString(stu.getColumnIndex("sNumber"));
        String sName = stu.getString(stu.getColumnIndex("sName"));
        String sAge = stu.getString(stu.getColumnIndex("sAge"));

        System.out.println("id:" + sNumber + "\t,name:" + sName + "\t,age:" + sAge);
    } while (stu.moveToNext());
} else {
    System.out.println("沒找到");
}

ContentProvider存儲數據

內容提供器(Content Provider)主要用於在不同的應用程序之間實現數據共享的功能,它提供了一套完整的機制,允許一個程序訪問另一個程序中的數據,不同於文件存儲和SharedPreferences存儲中的兩種全局可讀寫操作模式,內容提供器可以選擇只對哪一部分數據進行共享,從而保證我們程序中的隱私數據不會有泄漏的風險

詳細內容請參考文章《內容提供器ContentProvider

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章