数据存储-SQLite

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

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

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

XML 复制代码
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第2步:设计布局

XML 复制代码
<?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回调方法中动态请求权限,授权成功后,创建数据库

java 复制代码
 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步:逻辑文件

java 复制代码
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方法,创建一个数据库对象,需要两个参数

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

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

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

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

看个添加一行数据的案例

java 复制代码
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数据库操作,游标就非常简单了)

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

java 复制代码
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方法

相关推荐
太空漫步112 小时前
android社畜模拟器
android
m0_748255414 小时前
vscode配置django环境并创建django项目(全图文操作)
vscode·django·sqlite
海绵宝宝_5 小时前
【HarmonyOS NEXT】获取正式应用签名证书的签名信息
android·前端·华为·harmonyos·鸿蒙·鸿蒙应用开发
凯文的内存7 小时前
android 定制mtp连接外设的设备名称
android·media·mtp·mtpserver
天若子7 小时前
Android今日头条的屏幕适配方案
android
林的快手8 小时前
伪类选择器
android·前端·css·chrome·ajax·html·json
望佑8 小时前
Tmp detached view should be removed from RecyclerView before it can be recycled
android
xvch11 小时前
Kotlin 2.1.0 入门教程(二十四)泛型、泛型约束、绝对非空类型、下划线运算符
android·kotlin
人民的石头14 小时前
Android系统开发 给system/app传包报错
android
yujunlong391915 小时前
android,flutter 混合开发,通信,传参
android·flutter·混合开发·enginegroup