数据存储-SQLite

发布于:2024-05-06 ⋅ 阅读:(26) ⋅ 点赞:(0)

  一般使用到数据库存储,涉及到的数据量都较大,采用文件存储也能完成,但是文件操作复杂,效率低,大量结构化数据通常采用关系型数据库存储较为合适。Android中已经嵌入了轻量级的关系型数据库SQLite,直接按照数据库操作,实现增删改查即可。如果你想要完成一个简单增删改查作品,可以使用:UI设计+页面跳转+对话框+数据库技术架构。

  数据库操作一般分为两个步骤:创建数据库,接下来写SQL语句,执行并查看结果,常见操作为:增删改查。

第1步:配置权限(主要是因为API版本可能不同,配置一下权限较好,高版本都无需配置,我测试使用的是API34,所以我没有配置)

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第2步:设计布局

<?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:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="用户名" />

        <EditText
            android:id="@+id/username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入用户名" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="密    码" />

        <EditText
            android:id="@+id/pwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入密码" />
    </LinearLayout>

    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="增加" />

    <Button
        android:id="@+id/delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="删除" />

    <Button
        android:id="@+id/update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="修改" />

    <Button
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询" />

</LinearLayout>

设计图效果:

增加操作:输入用户名和密码,点击增加,往数据库中添加一条数据。

删除操作:根据用户输入的用户名,删除一条数据。(注:当然,如果不存在,删除肯定会失败,这些处理我就没有关注了,案例主要想表达的是能删除,如果需要做的精致或者实际开发中用到,请务必考虑周全)

修改操作:根据用户输入的用户名来更新密码,所以此时输入的密码,相当于是覆盖旧值。

查询操作:将表中的数据全部查出,并显示即可(实际开发中,结合ListView+ArrayAdapter效果更佳)

第3步:请求权限,并获得授权后,创建数据库。(如果你没有配置权限,则这一步都可以跳过了)

具体操作:在onCreate回调方法中动态请求权限,授权成功后,创建数据库

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            File file = new File("data/data/com.yibinu.sqlitedemo/testdb.db3");
            Log.i("目录", "onCreate: " + file);
            if (file.exists() && !file.isDirectory()) {
                sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(file, null);
                String sql = "create table testdb(username varchar(10),pwd varchar(6))";
                sqLiteDatabase.execSQL(sql);
            } else {
                Log.i("===============", "onCreate: 文件不存在");
            }
        }

如果你在测试时,创建失败,还可以去指定目录位置手动创建文件testdb.db3

由于我的测试版本较高,就没有去写授权,直接使用

第4步:逻辑文件

package com.yibinu.sqlitedemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button add;
    Button delete;
    Button update;
    Button query;

    EditText username;
    EditText pwd;

    SQLiteDatabase sqLiteDatabase = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        add = findViewById(R.id.add);
        delete = findViewById(R.id.delete);
        update = findViewById(R.id.update);
        query = findViewById(R.id.query);
        username = findViewById(R.id.username);
        pwd = findViewById(R.id.pwd);

        delete.setOnClickListener(this);
        add.setOnClickListener(this);
        update.setOnClickListener(this);
        query.setOnClickListener(this);

        File file = new File("data/data/com.yibinu.sqlitedemo/testdb.db3");
        Log.i("目录", "onCreate: " + file);
        if (file.exists() && !file.isDirectory()) {
            sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(file, null);
            String sql = "create table testdb(username varchar(10),pwd varchar(6))";
            sqLiteDatabase.execSQL(sql);
        } else {
            Log.i("===============", "onCreate: 文件不存在");
        }
    }
    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.add) {
            String userName = username.getText().toString().trim();
            String pWD = pwd.getText().toString().trim();
            String addSql = "insert into testdb(username,pwd) values(?,?);";
            sqLiteDatabase.execSQL(addSql, new String[]{userName, pWD});
            Toast.makeText(this, "插入数据成功", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.delete) {
            String delUserName = username.getText().toString().trim();
            String deleteSql = "delete from testdb where username=?";
            sqLiteDatabase.execSQL(deleteSql, new String[]{delUserName});
            Toast.makeText(this, "删除数据成功", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.update) {
            String newUserName = username.getText().toString().trim();
            String pWDD = pwd.getText().toString().trim();
            String updateSql = "update testdb set pwd=? where username = ?";
            sqLiteDatabase.execSQL(updateSql, new String[]{pWDD, newUserName});
            Toast.makeText(this, "更新数据成功", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.query) {
            String queryDateSql = "select * from testdb";
            Cursor cursor = sqLiteDatabase.rawQuery(queryDateSql, null);
            while (cursor.moveToNext()) {
                String myname = cursor.getString(0);
                String mypwd = cursor.getString(1);
                Log.i("【查询结果】", "姓名:" + myname + "密码:" + mypwd);
            }
            Toast.makeText(this, "查询成功,请查看日志", Toast.LENGTH_SHORT).show();
        }
    }
}

效果

运行成功后,出现主界面

接下来看动态演示

SQLite效果

核心技术:

SQLiteDatabase类,通过该类对象,可以执行SQL语句,具体操作,通过openOrCreateDatabase方法,创建一个数据库对象,需要两个参数

public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
            @Nullable CursorFactory factory) 
  1. 数据库名
  2. 游标工厂

当然,一般方法和构造方法都可以重载,所以如果你看到有多个参数,也可以查看一下原型,就可以直接使用了。

接下来就通过数据库对象,执行SQL语句,核心方法是:

public void execSQL(String sql, Object[] bindArgs)
  1. SQL语句
  2. 参数

看个添加一行数据的案例

String userName = username.getText().toString().trim();
String pWD = pwd.getText().toString().trim();
String addSql = "insert into testdb(username,pwd) values(?,?);";
sqLiteDatabase.execSQL(addSql, new String[]{userName, pWD});

前两行,获取用户输入的用户名和密码,第3行,构造一个SQL语句,如果有参数,就使用?占位置,第4行,执行SQL语句,由于有参数,所以要把真实的数据去替换?所占据的位置。如果没有参数,就写为null,执行结束后,数据库中就已经添加上该条数据了。

修改和删除是一样的道理,查询要复杂一点,它的复杂在于,数据库的主要功能就是查询,查询结果通常是多行数据,就需要使用到游标(如果你会Oracle数据库操作,游标就非常简单了)

查询可以是带参的,也可以是不带参数的

String queryDateSql = "select * from testdb";
            Cursor cursor = sqLiteDatabase.rawQuery(queryDateSql, null);
            while (cursor.moveToNext()) {
                String myname = cursor.getString(0);
                String mypwd = cursor.getString(1);
                Log.i("【查询结果】", "姓名:" + myname + "密码:" + mypwd);
            }

游标可以简单理解为指向这个结果集,第一次移动,则来到第一行,再移动一次,就来到第二行

所以只要移动后,数据不为空,则表示移动后的位置是有一条数据的,就可以获取到对应的值

移动主要依靠moveToNext方法,读取对应的值,则使用getXXX方法