Android学习笔记(6)——详解持久化技术

第六章 数据存储权方案——详解持久化技术

6.1 持久化技术简介

  1. 概述:Android 系统中主要提供了3种方式用于简单地实现数据持久化功能,即文件存储、SharedPreference存储以及数据库存储。当然,除了这3种方式之外,你还可以将数据保存在手机的SD卡中,不过使用文件、SharedPreference 或数据库来保存数据会相对更简单一些,
    而且比起将数据保存在SD卡中会更加地安全。

6.2 文件存储

6.2.1 将文件存储到文件中
  1. Context类中提供了一个openFileOutput()方法,这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这
    里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data//files/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_ PRIVATE
    和MODE APPEND。其中MODE_ PRIVATE 是默认的操作模式,表示当指定同样文件名的时候,
    所写入的内容将会覆盖原文件中的内容,而MODE_ APPEND 则表示如果该文件已存在,就往文
    件里面追加内容,不存在就创建新文件。

  2. 给主活动界面添加EditText控件用于录入数据

    <?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:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/type_something_here"
            android:id="@+id/edit"/>
    
    </LinearLayout>
    
  3. 修改主活动代码,使其再销毁活动时实现数据的存储:

    package com.example.filepersistencetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.widget.EditText;
    
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    
    public class MainActivity extends AppCompatActivity {
    
        private EditText edit;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            edit = (EditText) findViewById(R.id.edit);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            String inputText = edit.getText().toString();
            save(inputText);
        }
    
        public void save(String inputText) {		//存储数据逻辑
            FileOutputStream out = null;
            BufferedWriter writer = null;	
            try {
                out = openFileOutput("data", Context.MODE_PRIVATE);		//获得字节输出流
                writer = new BufferedWriter(new OutputStreamWriter(out));	//将字节流转换为字符流
                writer.write(inputText);	//写出数据
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (writer != null) {
                        writer.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
6.2.2 从文件中读取数据
  1. 概述:Context 类中还提供了一个openFileInput()方法,用于从文件中读取数据。这个方法要比openFile0utput()简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到/data/data//files/目录下去加载这个文件,并返回一个
    FileInputStream对象,得到了这个对象之后再通过Java流的方式就可以将数据读取出来了。

  2. 修改主活动代码,编写数据写入方法

    package com.example.filepersistencetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    
    public class MainActivity extends AppCompatActivity {
    
        private EditText edit;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            edit = (EditText) findViewById(R.id.edit);
            String inputText = load();		//输入数据
            if(!TextUtils.isEmpty(inputText)) {	
                edit.setText(inputText);
                edit.setSelection(1);	//设置Edit的光标位置
                Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            String inputText = edit.getText().toString();
            save(inputText);
        }
    
        public void save(String inputText) {
            FileOutputStream out = null;
            BufferedWriter writer = null;
            try {
                out = openFileOutput("data", Context.MODE_PRIVATE);
                writer = new BufferedWriter(new OutputStreamWriter(out));
                writer.write(inputText);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (writer != null) {
                        writer.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public String load() {		//数据写入方法
            FileInputStream in = null;
            BufferedReader read = null;
            StringBuilder content = new StringBuilder();
            try {
                in = openFileInput("data");		//设置数据源
                read = new BufferedReader(new InputStreamReader(in));
                String line = "";	
                while ((line = read.readLine()) != null) {
                    content.append(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(read != null) {
                    try {
                        read.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return content.toString();
        }
    }
    

6.3 SharedPreferences存储

  1. 概述:不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过
    **这个键把相应的值取出来。**而且SharedPreferences 还支持多种不同的数据类型存储,存什么数据类型就拿出什么数据类型
6.3.1 将数据存储到SharedPreferences中
  1. 概述:使用SharedPreference来存储数据,首先的获取到SharedPreferences对象。Android提供了3种方法用于得到SharedPreferences对象。

  2. 三种获得SharedPreferences对象的方式:

    1. Context类中的getSharedPreferences()方法:

      此方法接收两个参数,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个SharedPreferences 文件都是存放在/data/data//shared_ _prefs/
      目录下
      的。第二个参数用于指定操作模式,目前只有MODE _PRIVATE这一种模式可选,它是默认的操作模式,和直接传入0效果是相同的,表示只有当前的应用程序才可以对这个
      SharedPreferences文件进行读写。

    2. Activity类中的getPreferences()方法:

      这个方法和Context中的getSharedPreferences( )方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。

    3. PreferenceManager类中的getDefaultSharedPreferences()方法:

      这是一个静态方法,它接收一个Context 参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences 文件。得到了SharedPreferences 对象之后,就可以开始向SharedPreferences文件中存储数据了,主要可以分为3步实现。

  3. 使用步骤:

    • 调用SharedPreferences对象的edit()方法来获取一个SharedPreferences . Editor对象

    • 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用
      putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。

    • 调用apply()方法将添加的数据提交,从而完成数据存储操作。

  4. getDefaultSharedPreferences()方法,使用流程:

    为活动设置一个按钮

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

 <Button
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:id="@+id/save_data"
     android:text="@string/save_data"/>

</LinearLayout>

修改主活动代码,为按钮设置点击事件,点击事件为存储数据

package com.example.sharedpreferencestest;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveData = (Button) findViewById(R.id.save_data);
        saveData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                @SuppressLint("CommitPrefEdits")	
                //获取editor对象
                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                editor.putString("name", "Tom");	//向对象中添加数据
                editor.putInt("age", 28);
                editor.putBoolean("married", false);
                editor.apply();		//调用apply方法将添加的数据提交,完成数据的存储
            }
        });
    }
}
  1. 补充:此方式类似于map集合的存储的方式,它只会为唯一键匹配唯一值,相同键会在第二添加数据时覆盖第一次添加的数据,键相同时如果类型不一样,下面出现的将对上面出现的类型进行覆盖
6.3.2 从SharedPreferences中读取数据
  1. 为主活动添加一个按钮并为其设置带年纪事件:

    package com.example.sharedpreferencestest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.annotation.SuppressLint;
    import android.app.Dialog;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button saveData = (Button) findViewById(R.id.save_data);
            saveData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    @SuppressLint("CommitPrefEdits")
                    SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                    editor.putString("name", "Tom");
                    editor.putInt("age", 28);
                    editor.putBoolean("married", false);
                    editor.apply();
    
                    Button restoreData = (Button) findViewById(R.id.restore_data);
                    restoreData.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            SharedPreferences pre = getSharedPreferences("data", MODE_PRIVATE);
                            String name = pre.getString("name", "");
                            int age = pre.getInt("age", 0);
                            boolean married = pre.getBoolean("married", false);
                            Log.d(TAG, "name is " + name);	//将数据打印出来
                            Log.d(TAG, "age is " + age);
                            Log.d(TAG, "married is " + married);
                        }
                    });
                }
            });
        }
    }
    

    结果展示:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zd4KwhvY-1631454087612)(C:\Users\过客\AppData\Roaming\Typora\typora-user-images\image-20210803114536805.png)]

6.3.3 实现记住密码功能
  1. 新控件,CheckBox:这是一个复选框控件,用户可以通过点击的方式来进行选中或取消。

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <CheckBox	//添加复选框控件
                android:id="@+id/remember_pass"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/remember_password"
                android:textSize="18sp" />
    
        </LinearLayout>
    
  2. 再主活动设置记住密码的处理逻辑:(先判断是否点击爆粗密码的复选框,点击则通过SharedPreferences对账号密码进行存储,下次登录将其拿出,未点击则清空存储的信息)

    package com.example.broadcastbestpractice;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.preference.PreferenceManager;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class LoginActivity extends AppCompatActivity {
    
        private SharedPreferences pref;
    
        private SharedPreferences.Editor editor;
    
        private EditText accountEdit;
    
        private EditText passwordEdit;
    
        private Button login;
    
        private CheckBox rememberPass;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            pref = PreferenceManager.getDefaultSharedPreferences(this);
            accountEdit = (EditText) findViewById(R.id.account);
            passwordEdit = (EditText) findViewById(R.id.password);
            rememberPass = (CheckBox) findViewById(R.id.remember_pass);
            login = (Button) findViewById(R.id.login);
            boolean isRemember = pref.getBoolean("remember_password", false);	//通过存储的数据判断是否为保存账号状态
            if(isRemember) {	//是则将数据拿出
                String account = pref.getString("account", "");
                String password = pref.getString("password", "");
                accountEdit.setText(account);
                passwordEdit.setText(password);
                rememberPass.setChecked(true);
            }
            login.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String account = accountEdit.getText().toString();
                    String password = passwordEdit.getText().toString();
                    if (account.equals("admin") && pass	word.equals("123456")) {
                        editor = pref.edit();	//保存数据
                        if(rememberPass.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();
                    }
                }
            });
        }
    }
    

6.4 SQLite 数据库

6.4.1 创建数据库
  1. 概述:Android为了让我们能够更加方便地管理数据库,专广]提供了一个SQLiteOpenHelper帮助类
    借助这个类就可以非常简单地对数据库进行创建和升级。

  2. SQLiteOpenHelper类:此类为一个抽象类,含有两个抽象方法,onCreatae()和onUpgrade()

    1. 实例方法:两方法都可以创建或者打开一个现有数据库(存在则打开,否则则创建),并返回一个可对数据库进行读写操作的对象。不同:
      1. getReadableDatabase(): 当数据库不可写入时,将以只读的方式打开数据库
      2. getWritableDatabase(): 当数据库不可写入时,此方法将抛出异常
  3. 构造方法参数说明:

    1. SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即可
      这个构造方法中接收4个参数,第一个参数是Context,这个没什么好说的,必须要有它才能对数据库进行操作。第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor, 一般都是传入null第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。构建出SQLiteOpenHelper 的实例之后,
  4. 创建数据库需要创建表:需要使用建表语句

    ![

    ](C:\Users\过客\AppData\Roaming\Typora\typora-user-images\image-20210805104809457.png)

  5. SQLite的数据类型很简单,只有四种:

    1. integer 表示整型
    2. real表示浮点型
    3. text表示文本类型
    4. blob表示二进制类型
  6. 代码实现:(先创建自己的帮助类,让其继承SQLiteOpenHelper帮助类,借助这个类就可以非常简单的对数据库进行创建和升级)

    package com.example.databasetest;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.widget.Toast;
    
    public class MyDatabaseHelper extends SQLiteOpenHelper {		//建表
        public 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);	//将建表语句定义成为一个字符串常量,SQLiteDatabase的execSQL()方法
            Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();	//弹窗提示
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int olderVersion, int newVersion) {
    
        }
    }
    
    
  7. 创建数据库:

    package com.example.databasetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        protected MyDatabaseHelper dpHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dpHelper = new MyDatabaseHelper(this,"Book.dp", null, 1);	//传参
            Button createDatabase = (Button) findViewById(R.id.create_database);
            createDatabase.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dpHelper.getWritableDatabase();		//创建数据库
                }
            });
        }
    }
    
6.4…2 升级数据库
  1. 概述:通过onUpgrade()方法对数据库进行升级

  2. 修改MyDatabaseHelper中代码:

    package com.example.databasetest;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.widget.Toast;
    
    public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table Book ("
                + "id integer primary key autoincrement, "
                + "author text, "
                + "price real, "
                + "pages integer, "
                + "name text)";
    
        private static final String CREATE_CATEGORY = "create table Category ("		//加入category表
                + "id integer primary key autoincrement, "
                + "category_name text, "
                +"category_code integer)";
    
        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);
            db.execSQL(CREATE_CATEGORY);
            Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int olderVersion, int newVersion) {	//执行更细数据库方法
            db.execSQL("drop table if exists Book");	//判断是否存在此表,存在则删除
            db.execSQL("drop table if exists Category");
            onCreate(db);	//上面不删除则此处抛异常
        }
    }
    
    
  3. 当主活动中方法执行哪里的版本号大于之前的版本号,则会执行帮助类中的onUpgrade方法

6.4.3 添加数据
  1. 概述:其实我们可以对数据进行的操作无非有4种,即CRUD。其中C代表添加(Create), R代
    表查询( Retrieve), U代表更新( Update), D代表删除(Delete)。

  2. 前面我们已经知道,调用SQLiteOpenHelper的getReadableDatabase( )或getWritable-
    Database()方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个
    SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。

  3. SQLiteDatabase对象提供了一个insert()方法,这个方法专门用于添加数据。、

    参数:

    1. 第一个参数:表名,表示我们希望想拿张表添加数据

    2. 第二个参数:用于在未指定添加数据的情
      况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传人null

    3. 第三个参数:ContentValues对象,它提供了一系列的put方法重载 ,用于向ContentValues中添加数据。

  4. 修改主活动代码为:

    package com.example.databasetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ContentValues;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        protected MyDatabaseHelper dpHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dpHelper = new MyDatabaseHelper(this,"BookStore.dp", null, 2);
            Button createDatabase = (Button) findViewById(R.id.create_database);
            createDatabase.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dpHelper.getWritableDatabase();
                }
            });
    
            Button addData = (Button) findViewById(R.id.add_data);
            addData.setOnClickListener(new View.OnClickListener() {		//添加数据逻辑
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dpHelper.getWritableDatabase();		//获取SQLiteDatabase对象
                    ContentValues values = new ContentValues();	//创建 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);	//将数据存储进数据库
                    values.clear();
                    
                    values.put("name", "The Da Lost Symbol");
                    values.put("author", "Dan BBrown");
                    values.put("pages", 510);
                    values.put("price", 16.95);
                    db.insert("Book", null, values);
                }
            });
        }
    }
    
6.4.4 更新数据
  1. 概述:SQLiteDatabase中也提供了一个非常好用的update()方法,用于对数据进行更新,这个方法接收4
    个参数,第一个参数和insert()方法一样,也是表名,在这里指定去更新哪张表里的数据。第二个参数是ContentValues对象,要把更新数据在这里组装进去。第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行

  2. 修改主活动代码:

    package com.example.databasetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ContentValues;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        protected MyDatabaseHelper dbHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dbHelper = new MyDatabaseHelper(this, "BookStore.dp", null, 2);
            Button createDatabase = (Button) findViewById(R.id.create_database);
            createDatabase.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dbHelper.getWritableDatabase();
                }
            });
    
            Button addData = (Button) findViewById(R.id.add_data);
            addData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    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);
                    values.clear();
                    values.put("name", "The Da Lost Symbol");
                    values.put("author", "Dan BBrown");
                    values.put("pages", 510);
                    values.put("price", 16.95);
                    db.insert("Book", null, values);
                }
            });
    
            Button button = (Button) findViewById(R.id.update_data);	
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();		//获取SQLiteDatabase对象
                    ContentValues values = new ContentValues();		//创建ContentCValues对象
                    values.put("price", 10.99);		//
                    db.update("Book", values, "name = ?", new String[] {"The Da Vinci Code"});	//没看太懂
                }
            });
        }
    }
    
6.4.5 删除数据
  1. 概述:调用SQLiteDatabase中的delete 方法对数据库中内容进行删除,此方法传入三个参数,第一参数为表名,第二第三参数用于约束删除某一行或某几行的数据

     Button delete = (Button) findViewById(R.id.Delete);
            delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();		//获取SQLiteDatabase对像
                    db.delete("Book", "pages > ?", new String[] {"500"});	//约束条件为删除页数超过500页的书
                }
            });
        }
    
6.4.6 查询数据
  1. 概述:SQL的全称是Structured Query Language,翻译成中文就是结构化查询语言,SQlLiteDatabase中提供了一个query()方法,

  2. 参数:最短的一个方法重载也需要传人7个参数。那我们就先来看一下这7个
    参数各自的含义吧。第一个参数不用说,当然还是表名,表示我们希望从哪张表中查询数据。第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列第三、第四个参数用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。第五个参数用于指定需要去group by
    的列,不指定则表示不对查询结果进行group by操作。第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤第七个参数用于指定查询结果的排序方式,不指定
    则表示使用默认的排序方式

query()方法参数对应SQL部分描述
tablefrom table_name指定查询的表明
columnsselect column1, column2指定查询的列表
selectionwhere column = value指定where的约束条件
selectionArgs-为where中的占位符提供具体的值
groupBygroup by column指定需要的group by的列
havinghaving column = value对group by 后的结果进一步约束
orderByorder by column1,column2指定查询结果的排序方式
6.4.7 使用SQLite操作数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RFPJOvuQ-1631454087614)(C:\Users\过客\AppData\Roaming\Typora\typora-user-images\image-20210807114648012.png)]

6.5 使用LitePal操作数据库

6.5.1 LitePal简介
  1. 概述:LitePal是一款开源的Android数据库框架,它采用了对象关系映射( ORM )的模式,并将我
    们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表和增删改查的操作。LitePal的项目主页上也有详细的使用文档,地址是: htps://github.com/LitePalFramework/LitePal
6.5.2 配置LitePal

配置流程;

  1. 添加依赖:

        implementation 'org.litepal.guolindev:core:3.2.3'
    
  2. 在main下创建assets目录,然后再此目录下创建文件litepal.xml,修改其代码为:

    <?xml version="1.0" encoding="utf-8"?>
    <litepal>
        <dbname vaule="People" />
    
        <version value="1" />
    
        <list>
        </list>
    
        <!--<dbname>标签用于指定数据库名 <version>标签用于指定版本号 <list>标签用于指定所有的映射模型-->
    
    </litepal>
    
    

    解释:其中,标签用于指定数据库名,标签用于指定数据库版本号,
    标签用于指定所有的映射模型

  3. 在注册表中添加如下代码:(将其添加在标签下)

    android:name="org.litepal.LitePalApplication"
    
6.5.3 创建和升级数据库

创建数据库:

  1. 创建需要存储的数据类:(如此数据库添加book类,将想要存储的数据封装进类里面,为其添加get,set方法)

    package com.example.litepaltest;
    
    public class Book {
        private int id;
    
        private String author;
    
        private double price;
    
        private int pages;
    
        private String name;
    
        private String press;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public int getPages() {
            return pages;
        }
    
        public void setPages(int pages) {
            this.pages = pages;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPress() {
            return press;
        }
    
        public void setPress(String press) {
            this.press = press;
        }
    }
    
    
  2. 修改litepal.xml文件代码为:

    <?xml version="1.0" encoding="utf-8"?>
    <litepal>
        <dbname value="Book" />
        <version value="2" />
        <list>
            <mapping class="com.example.litepaltest.Book"/>		//将类的映射添加进来
            <mapping class="com.example.litepaltest.Category"/>
        </list>
    </litepal>
    
    
    
  3. 调用LitePal.getDatabase()方法创建数据库:

    Button create = (Button) findViewById(R.id.Create);
            create.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LitePal.getDatabase();		//点击按钮完成数据库的创建
                }
            });
    

更新数据库:

  1. 若只修改某一类的部分数据,则在类中修改:

  2. 若添加新的数据表,则现创建数据类型,然后将其映射关系添加到litepal.xml下的标签下

    创建类:

    package com.example.litepaltest;
    
    public class Category {
        private int id;
        private String categoryName;
        private int categoryCode;
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void setCategoryName(String categoryName) {
            this.categoryName = categoryName;
        }
    
        public void setCategoryCode(int categoryCode) {
            this.categoryCode = categoryCode;
        }
    }
    
    

    添加映射:

    <?xml version="1.0" encoding="utf-8"?>
    <litepal>
        <dbname value="Book" />
        <version value="2" />
        <list>
            <mapping class="com.example.litepaltest.Book"/>
            <mapping class="com.example.litepaltest.Category"/>		//将新的表添加进list标签内
        </list>
    </litepal>
    
    
  3. 最后记得将数据库的版本号加一,完成数据库的更新

6.5.4 使用LitePal添加数据
  1. 添加继承,让自己的数据类继承LitePalSupptor
public class Book extends LitePalSupport 
  1. 创建所存储数据的对象实例,然后向此对象中添加所需存储的数据,最后调用save() 将数据添加至数据库:
    Book book = new Book();
    book.setName("The Da Vinci Code");
    book.setAuthor("Dan brown");
    book.setPages(454);
    book.setPrice(16.96);
    book.setPress("UnKnow");
    book.save();
6.5.5 使用LitePal更新数据
  1. 通过获取对象实例类对所存储的数据进行更新:(可通过LitePal提供的查询API查询出来对象实例,然后对其修改在进行存储,实现数据的更新)

        Button upData = (Button) findViewById(R.id.Update);
        upData.setOnClickListener(view -> {
            Book book = new Book();       //只能对一存储的对像实例进行操作
            book.setName("The Lost Symbol");
            book.setAuthor("Dan Brown");
            book.setPages(510);
            book.setPrice(19.96);
            book.setPress("UnKnow");
            book.save();	//对此对象进行存储
            book.setPrice(10.99);
            book.save();	//由于此对象已经被存储过了,所以此save只会对此对象的数据进行修改
        });
    
  2. 通过调用updateAll()方法对数据进行更新:

        Button upData = (Button) findViewById(R.id.Update);
        upData.setOnClickListener(view -> {
            Book book = new Book();		//创建Book对象
            book.setPrice(16.95);
            book.setAuthor("Dan Brown");
            book.setPress("Anchor");	//设置想要更新的数据
            book.updateAll("name = ?","The Lost Symbol");	//调用方法对数据进行更新,添加约束条件,此约束条件为书名为The Lost Symbol的对象,执行结果为会将所有书名为此的数据的那三条数据更新
        });
    
  3. 将数据更新为默认值的操作,LitePal统一提供了一个setToDefault()方法,传入响应的列名即可

        Book book = new Book();
        book.setToDefault("pages");
        book.updateAll();
    

    这段代码的意思是,将所有书的页数都更新为0,因为updateAll()方法中没有指定约束件,因此更新操作对所有数据都生效了。

6.5.6 使用LitePal删除数据
  1. 通过获取存储的数据对象实例,然后调用delete()方法类删除数据

  2. 使用deleteAll()方法类删除数据:使用LitePal.deleteAll()方法

     Button delData = (Button) findViewById(R.id.Delete);
            delData.setOnClickListener(View -> {
                LitePal.deleteAll(Book.class, "price < ?", "16.96");	//约束条件为价格低于16.96的书
            });
    

3 若不指定约束条件则删除全部数据

6.5.7 使用LitePal查询数据
  1. LitePal调用findAll()方法,返回一个List集合,将数据库中此表的数据全部拿出

        Button query = (Button) findViewById(R.id.Query);
        query.setOnClickListener(View -> {
            List<Book> books = LitePal.findAll(Book.class);
            for(Book book:books) {
                Log.d("MainActivity", "book name is " + book.getName());
                Log.d("MainActivity", "book author is " + book.getAuthor());
                Log.d("MainActivity", "book pages is " + book.getPages());
                Log.d("MainActivity", "book price is " + book.getPrice());
                Log.d("MainActivity", "book press is " + book.getPress());
            }
        });
    
  2. LitePal的查询API:

    1. 查询Book表中的第一条数据:

      Book firstBook = LitePal.findFirst(Book.class);

    2. 查询Book表中的最后一条数据

      Book lastBook = LitePal.findLast(Book.class);

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zcctXnaj-1631454087616)(C:\Users\过客\AppData\Roaming\Typora\typora-user-images\image-20210808115747983.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值