1. 程式人生 > >第二行程式碼學習筆記——第六章:資料儲存全方案——詳解持久化技術

第二行程式碼學習筆記——第六章:資料儲存全方案——詳解持久化技術

本章要點

任何一個應用程式,總是不停的和資料打交道。
瞬時資料:指儲存在記憶體當中,有可能因為程式關閉或其他原因導致記憶體被回收而丟失的資料。
資料持久化技術,為了解決關鍵性資料的丟失。

6.1 持久化技術簡介

資料持久化技術:指那些記憶體中的瞬時資料儲存到裝置當中,保證手機和電腦關機的情況下,資料不會丟失。
儲存在記憶體中的資料是瞬時資料,而儲存在儲存裝置中的資料是處於持久化狀態的,持久化救贖提供了可以讓資料在瞬時資料和持久狀態進行轉換。
Android系統中提供了3種方式用於簡單的實現資料持久化功能,即檔案儲存,SharePreferences儲存資料庫儲存(更安全)。還有我們可以將資料儲存到SD卡中(不安全)。

6.2檔案儲存

檔案儲存是Android中最基本的一種儲存方式,適合用於儲存一些簡單的文字資料和二進位制資料。

6.2.1 將資料儲存到檔案中

Content類提供了一個openFileOutput()方法,可以用於將資料儲存到檔案中。接收兩個引數,第一引數的檔名,在檔案建立的時候使用的就是這個名字(不可包含路徑,預設儲存到/data/data/< packagename/>/files/目錄下的);第二個引數檔案的操作模式(可選),分為MODE_PRIVATE(預設的操作模式,當指定同樣的檔名的時候,所寫的內容將會覆蓋原始檔的內容)和MODE_APPEND(如果檔案存在,就往裡面追加內容,不存在就建立新檔案)。

openFileOutput()方法返回的是FileOutputStream物件,如何將一段文字儲存到檔案中,程式碼如下:

    public void save() {
        String data = "Data to save";
        try {
            fileOutputStream = openFileOutput("data", MODE_PRIVATE);
            bufferedWriter=new BufferedWriter(new OutputStreamWriter(fileOutputStream));
            bufferedWriter.write(data);
        }  catch
(IOException e) { e.printStackTrace(); }finally { try { if (bufferedWriter!=null){ bufferedWriter.close();} } catch (IOException e) { e.printStackTrace(); } } } }

建立FilePersistenceTest專案,並修改activity_main中的程式碼如下:

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

    <EditText
        android:id="@+id/et_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type something here" />
</LinearLayout>

資料回收之前,將它儲存到檔案當中,修改MainAcitivty中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private EditText et_input;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_input= (EditText) findViewById(R.id.et_input);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String inputText = et_input.getText().toString();
        save(inputText);
    }

    public void save(String inputText) {
        FileOutputStream fileOutputStream = null;
        BufferedWriter bufferedWriter=null;
        try {
            fileOutputStream = openFileOutput("data", MODE_PRIVATE);
            bufferedWriter=new BufferedWriter(new OutputStreamWriter(fileOutputStream));
            bufferedWriter.write(inputText);
        }  catch (IOException e) {
            e.printStackTrace();
        }finally {

                try {
                    if (bufferedWriter!=null){
                    bufferedWriter.close();}
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

執行程式 ,輸入內容:
wjcc

然後我們按下Back鍵,這時輸入的內容已經儲存到檔案當中了。

檢視:導航欄中的Tools—>Android—>Android Device Monitor工具。點選File Explore標籤頁,/data/data/包名/files/目錄。

ck

左邊的按鈕可以將檔案匯出到電腦上
dc

用記事本開啟檔案:
dkwj

這樣,我們就把資料儲存下來了。下次啟動還能將資料還原到EditText,學習從檔案中讀取資料。

6.2.2 從檔案中讀取資料

Content提供了openFileInput()方法,從檔案中讀取資料。接收一個引數(讀取的檔名)。載入目錄下的檔案,返回FileInputStream物件。

從檔案中讀取資料,程式碼如下:

 public String load(){
        FileInputStream fileInputStream=null;
        BufferedReader bufferedReader=null;
        StringBuilder builder=new StringBuilder();
        try {
            fileInputStream = openFileInput("data");
            bufferedReader=new BufferedReader(new InputStreamReader(fileInputStream));
            String line="";
                while ((line=bufferedReader.readLine())!=null){
                    builder.append(line);
                }

        }  catch (IOException e) {
            e.printStackTrace();
        }
        finally {

                try {
                    if (bufferedReader!=null){
                    bufferedReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        return builder.toString();
    }

重新啟動顯示我們上次輸入的內容,修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private EditText et_input;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_input= (EditText) findViewById(R.id.et_input);

        String inputText = load();
        if (!TextUtils.isEmpty(inputText)){   //一次性進行兩種空值的判斷
            et_input.setText(inputText);
            et_input.setSelection(inputText.length());  //將游標移動到文字的末尾位置
            Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String inputText = et_input.getText().toString();
        save(inputText);
    }
    ...
    public String load(){
        FileInputStream fileInputStream=null;
        BufferedReader bufferedReader=null;
        StringBuilder builder=new StringBuilder();
        try {
            fileInputStream = openFileInput("data");
            bufferedReader=new BufferedReader(new InputStreamReader(fileInputStream));
            String line="";
                while ((line=bufferedReader.readLine())!=null){
                    builder.append(line);
                }

        }  catch (IOException e) {
            e.printStackTrace();
        }
        finally {

                try {
                    if (bufferedReader!=null){
                    bufferedReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        return builder.toString();
    }
}

這時我們執行程式,就會發現EditText顯示我們上次輸入的內容資訊:
dqsj

6.3 SharedPreferences儲存

SharedPreferences使用鍵值對的方式進行儲存的。當儲存一條資料,需要給這個資料提供一個對應的鍵,在讀取資料的時候通過鍵取值。支援多種不同的資料型別儲存。

6.3.1 將資料儲存到SharedPreferences中

使用SharedPreferences來儲存資料,首先獲取SharedPreferences物件。

Android中提供了3中獲取SharedPreferences物件的三種方式:

  1. Content類中得到getSharedPreferences()方法
    接收兩個引數,第一個引數用於指定SharedPreferences檔案的名稱,如果指定的檔案不存在,則會建立一個,SharedPreferences檔案存放在/data/data/< package name/>/shared_prefs/目錄下的。第二個引數操作模式,目前只有MODE_PRIVATE(預設的)一種。直接傳入0的效果是一樣的,表示只有當前應用程式才可以對這個SharedPreferences檔案進行讀寫。
  2. Activity類中getPreferences()方法
    只接受一個操作模式引數,因為這個方法會自動將當前活動的類名作為SharedPreferences的檔名。
  3. PreferenceManager類中的getDefaultSharedPreferences()方法
    靜態方法,接收一個Content引數,自動使用當前活動程式的包名作為字首來命名SharedPreferences檔案。

SharedPreferences檔案中儲存資料,主要分為3步實現:
(1) 呼叫SharedPreferences物件的edit()方法來獲取SharedPreferences.Editor物件。
(2) 向SharedPreferences.Editor物件中新增資料,比如新增字串使用putString()方法,以此類推。
(3) 呼叫apply()方法將新增的資料提交,完成資料儲存操作。

新建SharedPreferencesTest專案,修改activity_main.xml中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_save_data"
        android:text="Save Data"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private Button btn_save_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_save_data= (Button) findViewById(R.id.btn_save_data);
        btn_save_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                editor.putString("name","Jack");
                editor.putInt("age",21);
                editor.putBoolean("married",false);
                editor.apply();
            }
        });
    }
}

執行程式進入主介面後,點選Save Data按鈕。這時資料就已經儲存成功。我們File Explorer檢視,開啟檔案生成目錄,就可以看到生成了一個data.xml檔案:
scqsj

將檔案匯出到電腦上,用記事本開啟檢視:
ck

SharedPreferences檔案是用XML格式來對資料進行管理的。

6.3.2 從SharedPreferences中讀取資料

從SharedPreferences中讀取資料,SharedPreferences物件中提供了一些列的get方法(對應SharedPreferences.Editor中的put方法),用於對儲存的資料進行讀取。get方法都接受兩個引數,第一個引數就是鍵,第二個引數是預設值(表示當傳入的鍵找不到返回這個預設值)。

修改activity_main.xml中的程式碼如下:

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

    <Button
        android:id="@+id/btn_save_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Save Data"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/btn_restore_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Restore Data"
        android:textAllCaps="false" />

</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private Button btn_save_data,btn_restore_data;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_save_data= (Button) findViewById(R.id.btn_save_data);
        btn_restore_data= (Button) findViewById(R.id.btn_restore_data);
        ...
        btn_restore_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
                String name = pref.getString("name", "未知");
                int age = pref.getInt("age", 0);
                boolean married = pref.getBoolean("married", false);
                Log.d("MainActivty", "name:"+name);
                Log.d("MainActivty", "age:"+age);
                Log.d("MainActivty", "married:"+married);

            }
        });
    }
}

執行程式點選Restore Dataa按鈕,檢視logcat中的列印資訊:
slog

這樣我們就把之前所儲存的資料讀取出來了。SharedPreferences程式應用場景也不少。

6.3.3 實現記住密碼的功能

我們在上一章已經編寫了一個登入介面,開啟BroadcastBestPractice專案,修改login_main.xml檔案,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    ...
    <CheckBox
        android:id="@+id/cb_remember_password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Remember Password"
        android:textSize="18sp" />


    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="Login"
        android:textAllCaps="false" />

</LinearLayout>

CheckBox是一個複選框控制元件,表示使用者是否記住密碼。修改LoginActivity中的程式碼如下:

public class LoginActivity extends AppCompatActivity {

    private SharedPreferences pref;
    private SharedPreferences.Editor editor;

    private EditText et_account,et_password;
    private Button btn_login;
    private CheckBox cb_remember_password;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        pref= PreferenceManager.getDefaultSharedPreferences(this);

        et_account= (EditText) findViewById(R.id.et_account);
        et_password= (EditText) findViewById(R.id.et_password);
        btn_login= (Button) findViewById(R.id.btn_login);
        cb_remember_password= (CheckBox) findViewById(R.id.cb_remember_password);

        boolean isRemember=pref.getBoolean("remember_password",false);
        if (isRemember){
            //將賬號和密碼設定到文字框中
            String account = pref.getString("account", "");
            String password = pref.getString("password", "");
            et_account.setText(account);
            et_password.setText(password);
            cb_remember_password.setChecked(true);
        }

        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String account = et_account.getText().toString();
                String password = et_password.getText().toString();

                if (account.equals("admin")&&password.equals("123456")){

                    editor=pref.edit();
                    if (cb_remember_password.isChecked()){ //檢查複選框是否被選中
                        editor.putBoolean("remember_password",true);
                        editor.putString("account",account);
                        editor.putString("password",password);
                    }else{
                        editor.clear();
                    }
                    editor.apply();

                    Intent intent=new Intent(LoginActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }else{
                    Toast.makeText(LoginActivity.this, "account or password is invalid", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

執行程式,輸入賬號admin密碼123456,並選中密碼複選框,點選登入,就會跳轉到MainActivity。點選MainActivity中的下線廣播,回到登入介面,賬號密碼就會自動填充到街面上:

cf

ct

這樣,我們就是用SharedPreferences實現記住密碼的功能了。(不安全,正式的專案需要結合一定的加密演算法來對密碼的保護)。

6.4 SQLite資料庫儲存

SQLite是一款輕量級的關係型資料庫,它的運算速度非常快,佔用資源很少,只需要幾百KB記憶體,因而特別適合在移動裝置上。

SQlite不僅支援SQL語法,還遵循了資料庫的ACID事務。

6.4.1 建立資料庫

Android管理資料庫:SQLiteOpenHelper幫助類對資料庫進行建立和升級。

SQLiteOpenHelper的基本用法:SQLiteOpenHelper是一個抽象類,建立一個幫助類繼承自SQLiteOpenHelper,分別必須重寫onCreate()(建立)和onUpgrade()(升級)。

SQLiteOpenHelper中的getReadableDatabase()和getWritableDatabase(),建立或開啟現有的資料庫(如果資料庫已存在則直接開啟,否則一個新的資料庫),並返回一個對資料庫進行讀寫操作的物件。不同的是,當資料庫不可寫入的時候(如磁碟已滿),getReadableDatabase()只讀的方式開啟資料庫,而getWritableDatabase()則出現異常。

SQLiteOpenHelper有兩個構造方法可供重寫,一般使用引數較少的構造方法(接收4個引數)。第一個引數是Context。第二個引數是資料庫名稱。第三個引數允許我們在查詢資料的時候返回Cursor,一般傳入null。第四個引數表示當前資料的版本號,用於對資料庫進行升級操作。構建SQLiteOpenHelper例項之後,呼叫它的getReadableDatabase()或getWritableDatabase()就能建立資料庫。資料庫檔案存放在/data/data/< package name>/databases/目錄下。此時,重新onCreate()方法得到執行,處理建立表的邏輯。

建立DatabaseTest專案。
建立一個名為BookStore.db的資料庫,新建Book表,表中id(主鍵),作者,價格,頁數,書名等列。Book表的建表語句如下:

create table Book(
    id integer primary key autoincrement,
    author text,
    price real,
    pages integer,
    name text)

SQLite資料型別:integer 表示整型,real 表示浮點型,text 表示文字型別,blob 表示二進位制型別。primary key主鍵,autoincrement自增長。

新建MyDatabaseHelper類繼承自SQLiteOpenHelper,程式碼如下:

public class MyDatabaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_TABLE="create table Book("
            + "id integer primary key autoincrement,"
            + "author text,"
            + "price real,"
            + "pages integer,"
            + "name text)";

    private Context mContent;


    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContent=context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
        Toast.makeText(mContent, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

修改activity_main.xml中的程式碼,用於建立資料庫的按鈕,如下:

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

    <Button
        android:id="@+id/btn_create_database"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false" />

</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    private Button btn_create_database;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,1);
        btn_create_database= (Button) findViewById(R.id.btn_create_database);
        btn_create_database.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
    }
}

執行程式,點選Create Database按鈕,就會檢測當前程式沒有BookStore.db這個資料庫,然後呼叫MydatabaseHelper的onCreate()方法,彈出Toast建立成功。再點選按鈕就不會建立了。
cjsjk

換一種檢視方式,使用adb shell來對資料庫和表的建立情況進行檢查。

adb是Android SDK中自帶的除錯工具,可以直接對連線電腦的手機或模擬器進行除錯操作。它存放在sdk的platform-tools目錄下,使用adb,我們必須把它的路徑配置到環境變數裡。

Windows:右擊計算機—>屬性—>高階系統設定—>環境變數。在系統變數裡找到Path,點選編輯,將platform-tools配置進去。如圖:
adbhjbl

Linux或Mac系統,可以在home路徑下編輯.bash檔案,將platform-tools配置進去。

配置好環境變數,就可以使用adb工具了。開啟命令介面,輸入 adb shell,進入到裝置的控制檯。如圖:
sbkzt

使用cd命令進入到/data/data/com.example.hjw.databasetest/databases/目錄下,並使用 ls 命令檢視該目錄裡的檔案,如圖:
ckmlwj

這個目錄下有兩個檔案,一個是我們建立的BookStore.db,另一個BookStore.db-journal是為了讓資料庫能支援事務而產生的臨時檔案,一般這個檔案大小為0位元組。

藉助Sqlite命令開啟資料庫,鍵入sqlite3後面加資料庫名,如圖:
sqlite3

檢視資料庫中的表,鍵入 .table 命令,如圖:
table

此時的資料庫有兩張表:android_metadata是每個資料庫都會自動生成的(無視它)。Book就是我們通過MyDatabaseHelper進行建立的。通過 .schema 命令檢視它們的建表語句,如圖:
schema

鍵入.exit或.quit命令退出資料庫的編輯,再鍵入.exit退出控制檯。

6.4.2 升級資料庫

在我們的MyDatabaseHelper類中的onUpgrade()方法用於對資料庫的升級。
再新增一張Category表(id主鍵,分類名,分類程式碼)用於記錄圖書的分類,建表語句如下:

create table Category(
    id integer primary key autoincrement,
    category_name text,
    category_code integer)

將這條語句新增到MyDatabaseHelper類中,程式碼如下:

public class MyDatabaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_TABLE="create table Book("
            + "id integer primary key autoincrement,"
            + "author text,"
            + "price real,"
            + "pages integer,"
            + "name text)";
    public static final String CREATE_CATEGORY="create table Category("
            + "id integer primary key autoincrement,"
            + "category_name text,"
            + "category_code integer)";

    private Context mContent;


    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContent=context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContent, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }
}

在onUpgrade()方法執行兩條DROP語句,如果存在表就把刪了,在呼叫onCreate()重新建立。

修改MainActivity中MyDatabaseHelper構造方法的版本號,程式碼如下:

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    private Button btn_create_database;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
        btn_create_database= (Button) findViewById(R.id.btn_create_database);
        btn_create_database.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
    }
}

這裡指定資料庫的版本號為2,表示對資料庫進行升級。重新執行程式,點選Create Database按鈕,就會再次彈出建立成功。通過 adb shell 開啟BookStore.db資料庫,鍵入 .table 命令,如圖:
stable

鍵入.schema命令檢視建表語句,如圖:
sschema

由此可見Category表已經建立成功,升級完畢。

6.4.3 新增資料

對錶中的資料4中操作:即CRUD。C代表新增(create)insert,R代表查詢(Retrieve)select,U代表更新(Update)update,D代表刪除(Delete)delete。

呼叫SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法可用於建立和升級資料庫,返回SQLiteDatabase物件,對資料進行CRUD操作。

向資料庫中的表新增資料,SQLiteDatabase提供了insert()方法,接收3個引數,第一個引數是表名,第二個引數值未指定新增資料的情況下給某寫可為空的列自動賦值為NULL,直接傳入null即可。第三個引數是ContentValues物件,提供了put方法過載(用於新增資料)。

新增資料,修改activity_main中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    ...
    <Button
        android:id="@+id/btn_insert_data"
        android:textAllCaps="false"
        android:text="Insert Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    private Button btn_create_database,btn_insert_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
        btn_create_database= (Button) findViewById(R.id.btn_create_database);
        btn_insert_data= (Button) findViewById(R.id.btn_insert_data);
        ...
        btn_insert_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values=new ContentValues();
                values.put("name","第一行程式碼");
                values.put("author","郭霖");
                values.put("pages",545);
                values.put("price",54.5);
                db.insert("Book",null,values);  //插入第一條資料
                values.clear();
                values.put("name","Android群英傳");
                values.put("author","徐宜生");
                values.put("pages",421);
                values.put("price",48.9);
                db.insert("Book",null,values);  //插入第二條資料

            }
        });
    }
}

執行程式,點選Insert Data按鈕,資料新增成功。開啟BookStore.db檢視,輸入select * from Book;(注意:;必須加上才能查詢),如圖:
adds

我們可以看到剛才新增的資料。

6.4.4 更新資料

SQLiteDatabase中的update()方法,對資料進行更新,接收4個引數,第一個引數表名。第二個引數ContentValues物件(更新資料)。第三,四約束更新第幾行資料,預設更新所有行。

更新書的價格,修改activity_main中的程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    ...
    <Button
        android:id="@+id/btn_update_data"
        android:textAllCaps="false"
        android:text="Update Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    private Button btn_create_database,btn_insert_data,btn_update_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
        btn_create_database= (Button) findViewById(R.id.btn_create_database);
        btn_insert_data= (Button) findViewById(R.id.btn_insert_data);
        btn_update_data= (Button) findViewById(R.id.btn_update_data);
        ...
        btn_update_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values=new ContentValues();
                values.put("price","48.9");
                db.update("Book",values,"name = ?",new String[]{"第一行程式碼"});
            }
        });
    }
}

執行程式,點選以下Update Data按鈕,再次輸入查詢語句查詢表中的情況,如圖:
uselect

我們看到”第一行程式碼”的價格修改成功為48.9。

6.4.5 刪除資料

SQLiteDatabase中的delete()方法,對資料進行刪除,接收三個引數,第一個引數是表名。第二,三約束哪一行 ,預設刪除所有。

修改activity_main中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    ...
    <Button
        android:id="@+id/btn_delete_data"
        android:textAllCaps="false"
        android:text="Delete Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    private Button btn_create_database,btn_insert_data,btn_update_data,btn_delete_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
        btn_create_database= (Button) findViewById(R.id.btn_create_database);
        btn_insert_data= (Button) findViewById(R.id.btn_insert_data);
        btn_update_data= (Button) findViewById(R.id.btn_update_data);
        btn_delete_data= (Button) findViewById(R.id.btn_delete_data);
        ...
        btn_delete_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book","pages > ?",new String[]{"500"});
            }
        });
    }
}

執行程式,點選一下Delete Data按鈕,再次輸入查詢語句檢視,如下:
dselect

這樣超過500頁的書,就刪除了。

6.4.6 查詢資料

SQL的全稱是“結構化查詢語言(Structured Query Language)”。
SQLiteDatabase提供了query()方法用於對資料庫進行查詢。這個方法的引數非常複雜,最少的也需要傳入7個引數,第一個引數表名。第二個引數指定去查哪幾列(不指定預設查詢全部)。第三,第四個引數用於約束查詢一行或某幾行資料(不指定預設查詢所有行)。第五個引數用於指定group by的列(不指定預設不操作)。第六個引數對group by之後的資料進行過濾(不指定不進行過濾)。第七個引數指查詢結果的排序方式(不指定使用預設的排序方式)。參考下表:
qb

呼叫query()方法後返回Cursor物件,查詢到所有資料都從這個物件中取出。

修改activity_main.xml中的程式碼如下:

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

相關推薦

第二程式碼學習筆記——:資料儲存方案——持久化技術

本章要點 任何一個應用程式,總是不停的和資料打交道。 瞬時資料:指儲存在記憶體當中,有可能因為程式關閉或其他原因導致記憶體被回收而丟失的資料。 資料持久化技術,為了解決關鍵性資料的丟失。 6.1 持久化技術簡介 資料持久化技術:指那些記憶體中的瞬時

第一程式碼——資料儲存方案——持久化技術

目錄: 6.1 持久化技術簡介 6.2 檔案儲存 6.2.1 將資料儲存到檔案中 6.2.2 從檔案中讀出資料 6.3 SharedPreferences 儲存 6.3.1 將資料儲存到SharedPreferences中 6.3.2 從SharedPreferenc

第二程式碼學習筆記——:軟體也要拼臉蛋——UI開發的點點滴滴

本章要點 使用Android提供的UI來編寫程式介面。本章的內容就是學習UI方面的知識。 3.1 如何編寫程式介面 Android種編寫程式介面的方式: 1. 視覺化編輯器(不推薦) 2. 編寫XML程式碼(推薦) 3.2 常用控制元

第二程式碼學習筆記——:後臺默默的勞動者——探究服務

本章要點 Android沿用了諾基亞系統的Symbian作業系統的老習慣,從一開始就支援後臺功能,這使得應用程式即使在關閉的情況下仍然可以在後臺繼續執行。後臺功能屬於四大元件之一,重要程度言不可寓。 10.1 服務是什麼 服務(Service)是A

第二程式碼學習筆記——:手機平板要相容——探究碎片

本章要點 作為一名專業的Android開發人員,能夠同時相容手機和平板的開發時我們必須要做到的事情。 4.1 碎片是什麼 碎片(Fragment)是一種可以巢狀在活動當中的UI片段,它能讓程式更加合理和充分的利用大螢幕的控制元件。 4.2

第二程式碼學習筆記——第一:開始啟程——你的一行Android程式碼

筆者前言 最近在讀郭霖大神的第二行程式碼,藉助第二行程式碼,在這裡我認真梳理Android知識,為了形成自己的知識體系。堅持寫一系列關於第二行程式碼的學習筆記,一是來提升自己的學習能力,堅持每天學習; 二是給自己整理一份資料,方便以後的查閱與複習。希望能夠幫助

c++沈思錄 學習筆記 句柄(引用計數指針雛形?)

return 指針 使用權 -- play cpp open end 使用 一個簡單的point坐標類 class Point {public: Point():xval(0),yval(0){} Point(int x,int y):xval(x),yval(y)

o'Reill的SVG精髓(第二版)學習筆記——

使用 還需要 第四章 會有 屬性 輪廓 4.4 www. 進行 第四章:基本形狀 4.1線段 SVG可以使用<line>元素畫出一條直線段。使用時只需要指定線段起止點的x和y坐標即可。指定坐標時可以不帶單位,此時會使用用戶坐標,也可以帶上單位,如em、in等。

CLR via C#學習筆記--靜態類

eth clas cme rop () 接口 bstr field icm 6.4 靜態類 有一些永遠不需要實例化的類,例如Console,Math等。 這些類只有static成員。事實上,這種類的唯一作用就是組合一組相關的成員。 例如Math類就定義了一組執行數學運算的方

CLR via C#學習筆記--CLR如何調用虛方法、屬性和事件

style err rri 實參 寫代碼 調查 pre 好的 屬性 6.6.1 CLR如何調用虛方法、屬性和事件 本節重點是方法,但討論也與虛屬性和虛事件密切相關。屬性和事件實際作為方法實現,以後的章節會討論他們。 方法 方法代表在類型或類型的實例上執行某些操作的代碼。

CLR via C#學習筆記--對類型進行版本控制時的虛方法的處理

兩種 編譯器 當前 new 學習筆記 on() 定義 類定義 sealed 6.6.3 對類型進行版本控制時的虛方法的處理 如果類型要作為基類型使用,增加或修改它的成員時務必非常小心。 隱藏基類的同名實例方法 假定CompanyA定義了Phone類型 namespac

《機器學習》 周志華學習筆記 支援向量機(課後習題)python 實現

一、 1.間隔與支援向量 2.對偶問題 3.核函式 xi與xj在特徵空間的內積等於他們在原始yangben空間中通過函式k(.,.)計算的結果。 核矩陣K總是半正定的。 4.軟間隔與正則化 軟間隔允許某些samples不滿足約束  鬆弛變數 5.支援

C++primer 學習筆記—— 函式

一、函式基礎 函式:返回型別+函式名字+形參列表+函式體 通過呼叫運算子來執行函式。呼叫運算子的形式是一對圓括號,它作用於一個表示式,該表示式是函式或者指向函式的指標。 形參與實參 實參是形參的初始值。 實參的型別和數量必須與對應的形參型別和數量匹配。即使某個形參不

深度學習花書學習筆記 深度前饋網路

深度前饋網路又稱多層感知機、前饋神經網路。即只有從x向y方向的傳播,最終輸出y。 主要包括輸入層、隱藏層和輸出層。神經網路的模型可以解決非線性問題。 計算網路的引數通過反向傳播;如果每一層隱藏層都只有wx+b的運算,則多層累加變為w1*(w2*(w3*x))+a = W*

《C++ Primer Plus》學習筆記—— 分支語句和邏輯運算子(一)

本章內容包括: if 語句 if else 語句 邏輯運算子 &&、||和! cctype字元函式庫 條件運算子: ? : switch 語句 continue和break語句 讀取數字的迴圈 基本檔案輸入和輸出 if 語句 if (tes

第一程式碼 資料儲存方案

Android主要提供了3個方法實現資料的持久化功能 1、SharedPreference儲存;2、檔案儲存;3、資料庫儲存 1、檔案儲存 它是android中最基本的一種資料儲存方式。它不對儲存的內容做任何的格式化處理,將資料原封不動地儲存到檔案中。

資料分析 R語言實戰】學習筆記 引數估計與R實現(上)

6.1點估計及R實現 6.1.1矩估計 R中的解方程函式: 函式及所在包:功能 uniroot()@stats:求解一元(非線性)方程 multiroot()@rootSolve:給定n個(非線性)方程,求解n個根 uniroot.all()@rootSolve:

Lua學習筆記 深入函式

在Lua中,函式是一種第一類值,它們具有特定的詞法域; 第一類值表示函式與其他傳統型別的值具有相同的權利,函式可以儲存到變數中或table中, 可以作為實參傳遞給其他函式,還可以作為其他函式的返回值; 詞法域是指一個函式可以巢狀在另一個函式中,內部的函式可以訪問外部函式中的

Win32API學習筆記(二)

這次記錄的是一部分選單的內容(由於VS生成的已經比較全面了,所以這裡主要是講使用) // Win32ProjectRc.cpp : 定義應用程式的入口點。 // #include "stdafx.h" #include "Win32ProjectRc.h

《metasploit滲透測試魔鬼訓練營》學習筆記--客戶端滲透

                  攻擊者在溢位程式後,並不執行棧中的shellcode,而是尋找程式已載入模組中的一些特殊指令塊,配合棧上的壓棧引數,返回地址等資料,將這些孤立的指令塊聯絡起來,從而實現一定的功能,最終完成遠端程式碼執行的目標。但是在哪些苛刻的壞字元的限制條件下,實現的難度太大,根據這個思