Android 系统集成了一个轻量级的关系数据库—— SQLite。其优点是占用资源少,运行效率高、安全可靠、可移植性强,并且提供零配
置运行模式,适用于在资源有限的设备(如手机和平板电脑等)上进行数据存取。
在开发手机应用时,一般会通过代码来动态创建数据库,即在程序运行时,首先尝试打开数据库,如果数据库不存在,则自动创建该数据库,然后再打开数据库。下面介绍如何通过代码来创建以及操作数据库。
在 Android 的 SQLite 数据库中,提供了两种创建数据库的方法,分别是:
方法一:SQLiteDatabase 提供了openOrCreateDatabase() 方法来打开或创建一个数据库,语法如下:
static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)
例如,使用 openOrCreateDatabase() 方法创建一个名称为 user.db 的数据库的代码如下:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("user.db", null);
方法二: 通过 SQLiteOpenHelper 类创建数据库在 Android 中,提供了一个数据库辅助类 SQLiteOpenHelper。在该类的构造器中,调用Context 中的方法创建并打开一个指定名称的数据库。我们在应用这个类时,需要编写继承自SQLiteOpenHelper 类的子类,并且重写 onCreate() 和 onUpgrade() 方法。
本例着重介绍方法二的使用。
我们创建一个SQLiteOpenHelper的子类MySQLiteOpenHelper。代码如下:
MySQLiteOpenHelper.java
package com.example.mydemo;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "noteBase.db";
private static final int VERSION = 1;
//这是一条数据库常用语句,用于创建一个新表
private static final String table =
"create table " + DBSchema.TABLE_NAME +"("+
"_id integer primary key autoincrement,"+
DBSchema.UUID+","+
DBSchema.CONTENT+","+
DBSchema.DATE+")";
public MySQLiteOpenHelper(@Nullable Context context) {
//重写构造方法并设置工厂为null
super(context, DATABASE_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//下面的语句会执行数据库语句创建新表
db.execSQL(table);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public static class DBSchema{
public static final String TABLE_NAME = "custom";
public static final String UUID = "uuid";
public static final String CONTENT = "content";
public static final String DATE = "date";
}
}
SQLiteDatabase 类提供了 insert(……)(增)、update(……)(改)、delete(……) (删)和 query(……)(查) 方法,这些方法封装了执行增删改查操作的 SQL 命令,所以我们可以使用这些方法来完成对应的操作,而不用去编写 SQL 语句了。
(1)添加操作
SQLiteDatabase 类提供了 insert() 方法用于向表中插入数据。insert() 方法的基本语法格式如下:
public long insert (String table, String nullColumnHack, ContentValues values)
◆ table:用于指定表名。
◆ nullColumnHack:可选的,用于指定当 values 参数为空时,将哪个字段设置为 null,如果values 不为空,则该参数值可以设置为 null。
◆ values:用于指定具体的字段值,它相当于 Map 集合,也是通过键值对的形式存储值的。
(2)更新操作
SQLiteDatabase 类提供了 update() 方法用于更新表中的数据。update() 方法的基本语法格式如下:
public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
◆ table:用于指定表名。
◆ values:用于指定要更新的字段及对应的字段值,它相当于 Map 集合,也是通过键值对的形式存储值的。
◆ whereClause:用于指定条件语句,可以使用占位符(?)。
◆ whereArgs:当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
(3)删除操作
SQLiteDatabase 类提供了 delete() 方法用于从表中删除数据。delete() 方法的基本语法格式如下:
public int delete(String table, String whereClause, String[] whereArgs)
◆ table:用于指定表名。
◆ whereClause:用于指定条件语句,可以使用占位符(?)。
◆ whereArgs:当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
(4)查询操作
SQLiteDatabase 类提供了 query() 方法用于查询表中的数据。query() 方法的基本语法格式如下:
public Cursor query( String table, String[] columns, String selection, String[] selectionArgs, String groupBy,String having,String orderBy,String limit);
◆ table:用于指定表名。
◆ columns:用于指定要查询的列。若为空,则返回所有列。
◆ selection:用于指定 where 子句,即指定查询条件,可以使用占位符(?)。
◆ selectionArgs:where 子句对应的条件值,当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
◆ groupBy:用于指定分组方式。
◆ having:用于指定 having 条件。
◆ orderBy:用于指定排序方式,为空表示采用默认排序方式。
◆ limit:用于限制返回的记录条数,为空表示不限制。query() 方法的返回值为 Cursor 对象。该对象中保存着查询结果,但是这个结果并不是数据集合的完整复制,而是数据集的指针。通过它提供的多种移动方式,我们可以获取数据集合中的数据。
Cursor 类提供的常用方法如下表所示:
下面贴出源码:
MySQLiteOpenHelper.java与上面数据库的创建方法二相同,不在赘述。
Note.java
package com.example.mydemo;
import java.util.Date;
import java.util.UUID;
public class Note {
//给每个Note实例添加加一个唯一识别码,这个是独一无二的
private String uuId;
private String content;
private Date date;
public Note() {
this.date = new Date();
uuId = UUID.randomUUID().toString();
}
public void setUuId(String uuId) {
this.uuId = uuId;
}
public String getUuId() {
return uuId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getDate() {
return date;
}
public void setDate(long date) {
this.date = new Date(date);
}
}
NoteLab .java
package com.example.mydemo;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class NoteLab {
private static NoteLab sNoteLab;
private SQLiteDatabase database ;
//用于暂存数据库的数据
private List<Note> notes;
//留给外界的接口,用于得到NoteLab实例
public static NoteLab createNoteLab(Context context){
if (sNoteLab == null){
sNoteLab = new NoteLab(context);
}
return sNoteLab;
}
//构造方法私有,使得只能通过createNoteLab(……)方法创建NoteLab实例
private NoteLab(Context context) {
database = new MySQLiteOpenHelper(context).getWritableDatabase();
updateNotes();
}
//插入数据
public void addData(Note note) {
ContentValues values = getValues(note);
database.insert(MySQLiteOpenHelper.DBSchema.TABLE_NAME,null,values);
updateNotes();
}
//查询数据
public List<Note> queryData(String whereClause,String[] whereArgs) {
Cursor cursor = database.query(
MySQLiteOpenHelper.DBSchema.TABLE_NAME,
null,
whereClause,
whereArgs,
null,
null,
null
);
List<Note> notes = new ArrayList<>();
cursor.moveToFirst();
try{
while (!cursor.isAfterLast()){
notes.add(getNote(cursor));
cursor.moveToNext();
}
}
finally {
cursor.close();
}
return notes;
}
//在查询数据是使用,用于返回Note实例
private Note getNote(Cursor cursor) {
Note note = new Note();
String uuId = cursor.getString(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.UUID));
String content = cursor.getString(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.CONTENT));
long date = cursor.getLong(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.DATE));
note.setUuId(uuId);
note.setContent(content);
note.setDate(date);
return note;
}
//更新数据
public void updateDate(int position,String content) {
Note note = notes.get(position);
note.setContent(content);
ContentValues values = getValues(note);
database.update(
MySQLiteOpenHelper.DBSchema.TABLE_NAME,
values,
MySQLiteOpenHelper.DBSchema.UUID + "= ?",
new String[]{
note.getUuId()}
);
updateNotes();
}
//删除数据
public void deleteData(int position) {
Note note = notes.get(position);
database.delete(
MySQLiteOpenHelper.DBSchema.TABLE_NAME,
MySQLiteOpenHelper.DBSchema.UUID + "= ?",
new String[]{
note.getUuId()}
);
// database.delete(MySQLiteOpenHelper.DBSchema.TABLE_NAME,null,null);
Log.i("删除数据", "deleteData: "+position);
updateNotes();
}
//返回一个ContentValues实例,方便插入和更新数据使用
private ContentValues getValues(Note note) {
ContentValues values = new ContentValues();
String uuId = note.getUuId();
String content = note.getContent();
long date = note.getDate().getTime();
values.put(MySQLiteOpenHelper.DBSchema.UUID,uuId);
values.put(MySQLiteOpenHelper.DBSchema.CONTENT,content);
values.put(MySQLiteOpenHelper.DBSchema.DATE,date);
return values;
}
//用于更新暂存数据库的数据实例notes
private void updateNotes() {
notes = queryData(null,null);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#E2DFDF"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:background="#ffffff"
android:text="/????????????????/"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="日期:"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:background="#ffffff"
android:hint="请输入内容 !"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_date"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/et_flag"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#ffffff"
android:gravity="center"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="@+id/btn_confirm"
app:layout_constraintEnd_toEndOf="@+id/btn_num"
app:layout_constraintStart_toStartOf="@+id/btn_num"
app:layout_constraintTop_toTopOf="@+id/btn_update" />
<Button
android:id="@+id/btn_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:text="插入数据"
android:textSize="25sp"
app:layout_constraintEnd_toStartOf="@+id/et_flag"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_content" />
<Button
android:id="@+id/btn_query"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:text="查询结果"
android:textSize="25sp"
app:layout_constraintEnd_toStartOf="@+id/btn_num"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_confirm" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:text="内容:"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_query_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_query_content" />
<TextView
android:id="@+id/tv_query_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:background="#ffffff"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView3"
app:layout_constraintTop_toBottomOf="@+id/btn_query" />
<Button
android:id="@+id/btn_update"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:text="更新数据"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/et_flag"
app:layout_constraintTop_toTopOf="@+id/btn_confirm" />
<Button
android:id="@+id/btn_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:text="删除数据"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_num"
app:layout_constraintTop_toTopOf="@+id/btn_query" />
<Button
android:id="@+id/btn_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="数据量"
app:layout_constraintBottom_toBottomOf="@+id/btn_query"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_flag" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity .java
package com.example.mydemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button mBtnConfirm;
private Button mBtnQuery;
private Button mBtnUpdate;
private Button mBtnDelete;
private Button mBtnDataNum;
private EditText mEtContent;
private EditText mEtFlag;
private TextView mTvDate;
private TextView mTvContentQuery;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定布局中的控件
initView();
//为各个控件设置执行命令
initEvent();
}
//得到当前数据库有多少条数据
private int getNoteNum() {
int noteNum = NoteLab.createNoteLab(getApplicationContext())
.queryData(null,null)
.size();
return noteNum;
}
private void initEvent() {
mEtFlag.setText(getNoteNum() + "");
mEtContent.setText("");
//插入数据
mBtnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mEtContent.getText().toString().length() != 0){
Note note = new Note();
note.setContent(mEtContent.getText().toString());
mTvDate.setText(note.getDate().toString());
mEtContent.setText("");
NoteLab.createNoteLab(getApplicationContext()).addData(note);
}
else {
Toast.makeText(MainActivity.this,"插入数据失败 !",Toast.LENGTH_SHORT)
.show();
}
}
});
//查询数据
mBtnQuery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<Note> notes = NoteLab.createNoteLab(getApplicationContext())
.queryData(null,null);
int position = Integer.parseInt(mEtFlag.getText().toString())-1;
if ((position >= 0) && (position < getNoteNum())){
Note note = notes.get(position);
mTvContentQuery.setText(note.getContent()+"\n\n"+note.getDate());
}
else {
mTvContentQuery.setText("");
Toast.makeText(MainActivity.this,"查询数据失败 !",Toast.LENGTH_SHORT)
.show();
}
}
});
//更新数据
mBtnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = Integer.parseInt(mEtFlag.getText().toString())-1;
if ((position >= 0) && (position < getNoteNum())){
Log.i("更新数据position",position+"");
Log.i("更新数据getNoteNum",getNoteNum()+"");
NoteLab.createNoteLab(getApplicationContext())
.updateDate(position,mEtContent.getText().toString());
}
else {
Toast.makeText(MainActivity.this,"更新数据失败 !",Toast.LENGTH_SHORT)
.show();
}
}
});
//删除数据
mBtnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = Integer.parseInt(mEtFlag.getText().toString())-1;
if ((position >= 0) && (position < getNoteNum())){
NoteLab.createNoteLab(getApplicationContext())
.deleteData(position);
}
else {
Toast.makeText(MainActivity.this,"删除数据失败 !",Toast.LENGTH_SHORT)
.show();
}
}
});
//获取数据量
mBtnDataNum.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEtFlag.setText(getNoteNum()+"");
}
});
}
private void initView() {
mBtnConfirm = findViewById(R.id.btn_confirm);
mBtnQuery = findViewById(R.id.btn_query);
mBtnUpdate = findViewById(R.id.btn_update);
mBtnDelete = findViewById(R.id.btn_delete);
mBtnDataNum = findViewById(R.id.btn_num);
mEtContent = findViewById(R.id.et_content);
mEtFlag = findViewById(R.id.et_flag);
mTvDate = findViewById(R.id.tv_date);
mTvContentQuery = findViewById(R.id.tv_query_content);
}
}
链接:百度网盘下载 提取码:0d1d