(二十二)安卓开发中的数据存储之SQLite简单使用
在Android开发中,SQLite是一种非常常用的数据库存储方式。它轻量、简单,非常适合移动设备上的数据管理。本文将通过通俗易懂的语言,结合代码示例和具体场景,详细讲解SQLite在Android中的使用。
1. 什么是SQLite?
SQLite是一个开源的、嵌入式的关系型数据库。它不需要像MySQL那样运行一个独立的服务器,而是直接将数据存储在一个文件中。这个文件可以随着你的应用一起打包,方便管理。简单来说,SQLite就像一个“便携式笔记本”,你可以在里面记录和管理数据。
2. 为什么在Android中使用SQLite?
- 轻量级: SQLite占用资源少,适合手机这种硬件资源有限的设备。
- 无需服务器: 不需要额外的服务器支持,直接嵌入应用中使用。
- 自包含: 数据库文件独立存在,易于备份和分发。
- 支持SQL: 使用标准的SQL语法,如果你学过数据库,上手会很快。
总之,SQLite是Android开发中内置的“标配”数据库,特别适合存储结构化数据,比如用户信息、任务列表等。
3. SQLite在Android中的基本使用步骤
使用SQLite主要涉及以下几个步骤:
- 创建数据库: 通过
SQLiteOpenHelper类来创建和管理数据库。 - 定义表结构: 在
onCreate方法中用SQL语句创建表。 - 插入数据: 往表里添加数据。
- 查询数据: 从表中读取数据。
- 更新数据: 修改表中的数据。
- 删除数据: 删除表中的数据。
接下来,我们通过代码和一个具体的通讯录应用场景来详细讲解这些步骤。
4. 代码示例
4.1 创建数据库和表
首先,我们需要创建一个类继承SQLiteOpenHelper,用来管理数据库和表的创建。
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;public class DatabaseHelper extends SQLiteOpenHelper {private static final String DATABASE_NAME = "my_database.db"; // 数据库文件名private static final int DATABASE_VERSION = 1; // 数据库版本号public DatabaseHelper(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {// 创建表的SQL语句String createTableSQL = "CREATE TABLE users (" +"id INTEGER PRIMARY KEY AUTOINCREMENT," + // 主键,自增"name TEXT," + // 姓名,文本类型"age INTEGER)"; // 年龄,整型db.execSQL(createTableSQL); // 执行SQL,创建表}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 数据库升级时执行,比如删除旧表并重建db.execSQL("DROP TABLE IF EXISTS users");onCreate(db);}
}
DATABASE_NAME: 数据库文件名,通常以.db结尾。DATABASE_VERSION: 数据库版本号,如果表结构有变化,需要增加版本号。onCreate: 第一次创建数据库时调用,定义表的结构。onUpgrade: 当版本号变化时调用,用于处理旧数据迁移。
4.2 插入数据
插入数据可以用insert方法,简单高效。
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;public void insertUser(String name, int age) {SQLiteDatabase db = getWritableDatabase(); // 获取可写数据库对象ContentValues values = new ContentValues(); // 用于存放键值对values.put("name", name); // 插入姓名values.put("age", age); // 插入年龄db.insert("users", null, values); // 插入到users表db.close(); // 关闭数据库连接
}
getWritableDatabase(): 获取一个可以读写的数据库对象。ContentValues: 像一个“包裹”,把要插入的数据装进去。insert: 将数据插入表中。
4.3 查询数据
查询数据可以用query方法,返回一个Cursor对象,类似于指针,指向查询结果。
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;class User {int id;String name;int age;public User(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}
}public List<User> getAllUsers() {List<User> userList = new ArrayList<>();SQLiteDatabase db = getReadableDatabase(); // 获取只读数据库对象Cursor cursor = db.query("users", null, null, null, null, null, null); // 查询所有数据if (cursor.moveToFirst()) { // 移动到第一条数据do {int id = cursor.getInt(cursor.getColumnIndex("id"));String name = cursor.getString(cursor.getColumnIndex("name"));int age = cursor.getInt(cursor.getColumnIndex("age"));User user = new User(id, name, age);userList.add(user);} while (cursor.moveToNext()); // 移动到下一条数据}cursor.close(); // 关闭游标db.close(); // 关闭数据库return userList;
}
getReadableDatabase(): 获取只读数据库对象。Cursor: 查询结果的“指针”,可以逐行读取数据。moveToFirst和moveToNext: 控制游标移动,遍历所有数据。
4.4 更新数据
更新数据可以用update方法。
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;public void updateUser(int id, String newName, int newAge) {SQLiteDatabase db = getWritableDatabase();ContentValues values = new ContentValues();values.put("name", newName);values.put("age", newAge);db.update("users", values, "id=?", new String[]{String.valueOf(id)}); // 根据id更新db.close();
}
update: 参数分别是表名、更新内容、条件和条件值。
4.5 删除数据
删除数据可以用delete方法。
import android.database.sqlite.SQLiteDatabase;public void deleteUser(int id) {SQLiteDatabase db = getWritableDatabase();db.delete("users", "id=?", new String[]{String.valueOf(id)}); // 根据id删除db.close();
}
delete: 参数分别是表名、条件和条件值。
5. 具体使用场景:通讯录应用
假设我们要开发一个简单的通讯录应用,存储联系人的姓名和电话号码。以下是如何用SQLite实现这个功能。
5.1 创建数据库和表
修改DatabaseHelper中的表结构:
@Override
public void onCreate(SQLiteDatabase db) {String createTableSQL = "CREATE TABLE contacts (" +"id INTEGER PRIMARY KEY AUTOINCREMENT," +"name TEXT," +"phone TEXT)";db.execSQL(createTableSQL);
}
5.2 插入联系人
public void insertContact(String name, String phone) {SQLiteDatabase db = getWritableDatabase();ContentValues values = new ContentValues();values.put("name", name);values.put("phone", phone);db.insert("contacts", null, values);db.close();
}
5.3 查询所有联系人
class Contact {int id;String name;String phone;public Contact(int id, String name, String phone) {this.id = id;this.name = name;this.phone = phone;}
}public List<Contact> getAllContacts() {List<Contact> contactList = new ArrayList<>();SQLiteDatabase db = getReadableDatabase();Cursor cursor = db.query("contacts", null, null, null, null, null, null);if (cursor.moveToFirst()) {do {int id = cursor.getInt(cursor.getColumnIndex("id"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));Contact contact = new Contact(id, name, phone);contactList.add(contact);} while (cursor.moveToNext());}cursor.close();db.close();return contactList;
}
5.4 更新联系人信息
public void updateContact(int id, String newName, String newPhone) {SQLiteDatabase db = getWritableDatabase();ContentValues values = new ContentValues();values.put("name", newName);values.put("phone", newPhone);db.update("contacts", values, "id=?", new String[]{String.valueOf(id)});db.close();
}
5.5 删除联系人
public void deleteContact(int id) {SQLiteDatabase db = getWritableDatabase();db.delete("contacts", "id=?", new String[]{String.valueOf(id)});db.close();
}
通过这些代码,我们可以实现一个简单的通讯录功能:添加联系人、查看所有联系人、修改联系人信息和删除联系人。
6. 注意事项
- 数据库版本管理: 如果表结构变了(比如增加字段),需要更新
DATABASE_VERSION,并在onUpgrade中处理旧数据。 - 线程安全: 数据库操作不要阻塞主线程,可以用
AsyncTask或线程池来处理。 - 关闭连接: 操作完数据库后,记得调用
close()释放资源。 - 异常处理: 操作数据库时可能会出错,要用
try-catch捕获异常,比如SQLiteException。
7. 总结
SQLite是Android开发中强大又简单的数据库工具。通过SQLiteOpenHelper和SQLiteDatabase,我们可以轻松实现数据的增删改查。结合通讯录这个例子,你应该已经掌握了SQLite的基本用法。在实际开发中,还可以根据需要使用更复杂的查询语句或事务管理,进一步提升应用的性能和功能。
相关文章:
(二十二)安卓开发中的数据存储之SQLite简单使用
在Android开发中,SQLite是一种非常常用的数据库存储方式。它轻量、简单,非常适合移动设备上的数据管理。本文将通过通俗易懂的语言,结合代码示例和具体场景,详细讲解SQLite在Android中的使用。 1. 什么是SQLite? SQLite是一个开…...
图像形态学操作对比(Opencv)
形态学基于图像的形状进行操作,用于处理二值化图像,主要包括腐蚀和膨胀两种基本操作。这些操作通常用于去除噪声、分隔或连接相邻的元素以及寻找图像中显著的最大点和最小点。 1. 形态学操作 import cv2 import numpy as np import matplotlib.pyplot …...
复刻系列-星穹铁道 3.2 版本先行展示页
复刻星穹铁道 3.2 版本先行展示页 0. 视频 手搓~星穹铁道~展示页~~~ 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列官方的网站: 《崩坏:星穹铁道》3.2版本「走过安眠地的花丛」专题展示页现已上线复刻的网…...
请你说一说测试用例的边界
一、什么是测试用例的边界? 边界是指输入、输出、状态或操作的极限条件,是系统行为可能发生变化的临界点。例如: 输入字段的最小值、最大值、空值、超长值; 循环的第0次、第1次、最后一次; 时间相关的闰年、月末、跨时区操作等。 边界测试的核心思想是:缺陷更容易出现在…...
Linux:进程理解1(查看进程,创造进程,进程状态)
进程理解 (一)查看进程通过系统调用获取进程标示* (二)创造进程(fork)1. 创造的子进程的PCB代码数据怎么来?2.一个函数为什么有两个返回值?3. 为什么这里会有 两个 id值?…...
异形遮罩之QML中的 `OpacityMask` 实战
文章目录 🌧️ 传统实现的问题👉 效果图 🌈 使用 OpacityMask 的理想方案👉代码如下🎯 最终效果: ✨ 延伸应用🧠 总结 在 UI 设计中,经常希望实现一些“异形区域”拥有统一透明度或颜…...
如何为您的设计应用选择高速连接器
电气应用的设计过程需要考虑诸多因素,尤其是在设计高速网络时。许多连接器用户可能没有意识到,除了在两个互连之间组装导电线路之外,还需要考虑各种工艺。在建立高速连接并确保适当的信号完整性时,必须考虑蚀刻、公差、屏蔽等因素…...
mongodb 4.0+多文档事务的实现原理
1. 副本集事务实现(4.0) 非严格依赖二阶段提交 MongoDB 4.0 在副本集环境中通过 全局逻辑时钟(Logical Clock) 和 快照隔离(Snapshot Isolation) 实现多文档事务,事务提交时通过…...
【论文阅读】UniAD: Planning-oriented Autonomous Driving
一、Introduction 传统的无人驾驶采用了区分子模块的设计,即将无人驾驶拆分为感知规划控制三个模块,这虽然能够让无人驾驶以一个很清晰的结构实现,但是感知的结果在传达到规划部分的时候,会导致部分信息丢失,这势必会…...
upload-labs二次打
1(前端js绕过) 弹窗,先看看有没有js有,禁用js 禁用后就可以上传php文件了,然后我们就去访问文件,成功 2(MIME绕过) 先上传一个php文件试试,不行,.htaccess不行, 试试MIME类型&am…...
Flutter命令行打包打不出ipa报错
Flutter打包ipa报错解决方案 在Flutter开发中,打包iOS应用时可能会遇到以下错误: error: exportArchive: The data couldn’t be read because it isn’ in the correct format. 或者 Encountered error while creating the IPA: error: exportArchive…...
网页制作中的MVC和MVT
MVC(模型-视图-控制器)和MVT(模型-模板-视图)是两种常见的软件架构模式,通常用于Web应用程序的设计。它们之间的主要区别在于各自的组件职责和工作方式。 MVC(模型-视图-控制器): 模…...
C. Good Subarrays
time limit per test 2 seconds memory limit per test 256 megabytes You are given an array a1,a2,…,ana1,a2,…,an consisting of integers from 00 to 99. A subarray al,al1,al2,…,ar−1,aral,al1,al2,…,ar−1,ar is good if the sum of elements of this subarra…...
聊天室项目day4(redis实现验证码期限,实现redis连接池)
1.redis连接池操作和之前所学过的io_context连接池原理一样这里不多赘述,也是创建多个连接,使用时按顺序取出来。 2.知识补充redisConnect()函数建立与 Redis 服务器的非阻塞网络连接,成功返回 redisContext*(连接上下文指针&…...
提交至git
通过 Pull Request 提交代码 如果你无法直接推送到 master 分支(例如,因为分支保护或权限限制),通常的做法是将代码推送到一个新分支,并通过 Pull Request(或 Merge Request)提交代码࿱…...
0x06.Redis 中常见的数据类型有哪些?
回答重点 Redis 常见的数据结构主要有五种,这五种类型分别为:String(字符串)、List(列表)、Hash、Set(集合)、Zset(有序集合,也叫sorted set)。 String 字符串是Redis中最基本的数据类型,可以存储任何类型的数据,包括文本、数字和二进制数据。它的最大长度为512MB。 使…...
如何查看自己 Android App 的私有数据?从 `adb backup` 到数据提取全过程
🛠️ 如何查看自己 Android App 的私有数据?从 adb backup 到数据提取全过程 📌 前言:作为一名 Android 开发者,我常常想知道自己写的 App 在用户设备上的数据存储结构是怎样的,比如有没有数据写入成功、有…...
提权实战!
就是提升权限,当我们拿到一个shell权限较低,当满足MySQL提权的要求时,就可以进行这个提权。 MySQL数据库提权(Privilege Escalation)是指攻击者通过技术手段,从低权限的数据库用户提升到更高权限ÿ…...
Vue使用el-table给每一行数据上面增加一行自定义合并行
// template <template><el-table:data"flattenedData":span-method"objectSpanMethod"borderclass"custom-header-table"style"width: 100%"ref"myTable":height"60vh"><!-- 订单详情列 -->&l…...
ChromeOS 135 版本更新
ChromeOS 135 版本更新 一、ChromeOS 135 更新内容 1. ChromeOS 电池寿命优化策略 为了延长 Chromebook 的使用寿命,ChromeOS 135 引入了一项全新的电池充电限制策略 —— DevicePowerBatteryChargingOptimization,可提供更多充电优化选项,…...
国内协作机器手焊接领域领军人物分析
国内焊接协作机器手领域的专家涵盖学术界与产业界,他们在核心技术研发、行业标准制定及重大工程应用中发挥关键作用。以下从技术方向、行业贡献、典型案例三个维度展开分析: 一、学术界领军人物:理论创新与技术突破 1. 吴林(哈尔滨工业大学) 学术地位:中国焊接学会名誉…...
javaSE.Lambda表达式
如果一个接口中有且只有一个待实现的抽象方法,那么我们可以将匿名内部类简写为Lambda表达式。 简写规则 标准格式: (【参数类型 参数名称,】...) -> {代码语句, 包括返回值} 只有一行花括号{}可以省略。…...
【随身wifi】青龙面板保姆级教程
0.操作前必看 本教程基于Debian系统,从Docker环境。面板安装,到最后拉取脚本的使用。 可以拉库跑狗东京豆,elm红包等等,也可以跑写自己写的脚本,自行探索 重要的号别搞,容易黑号,黑号自己负责…...
Android 之美国关税问题导致 GitHub 403 无法正常访问,责任在谁?
这几天各国关税问题导致世界动荡不安,如今GitHub又无法正常访问,是不是Google到时候也无法正常使用了。...
深入解析 Android 图形系统:Canvas、Skia、OpenGL 与 SurfaceFlinger 的协作
在 Android 应用开发中,流畅的 UI 渲染是用户体验的核心。但你是否好奇,一个简单的 View 是如何从代码中的 onDraw() 方法一步步变成屏幕上的像素的?本文将从底层图形系统的视角,解析 Android 中 Canvas、Skia、OpenGL ES 和 Surf…...
4月13日星期日早报简报微语报早读
4月13日星期日,农历三月十六,早报#微语早读。 1、北京处置倒伏树木843棵,已全部处置完毕; 2、山西大同“订婚强奸案”本月16日二审宣判,一审男方被判3年刑; 3、今年我国快递业务量已突破500亿件…...
动态路由, RIP路由协议,RIPv1,RIPv2
动态路由 1、回顾 路由:从源主机到目标主机的过程 源主机发送数据给目标主机,源主机会查看自身的路由信息 如果目标主机是自己同网段,源主机查看的是直连路由 如果目标主机和自己不同网段,源主机查看的是静态路由、动态路由、默…...
【已更新完毕】2025泰迪杯数据挖掘竞赛B题数学建模思路代码文章教学:基于穿戴装备的身体活动监测
基于穿戴装备的身体活动监测 摘要 本研究基于加速度计采集的活动数据,旨在分析和统计100名志愿者在不同身体活动类别下的时长分布。通过对加速度数据的处理,活动被划分为睡眠、静态活动、低强度、中等强度和高强度五类,进而计算每个志愿者在…...
212、【图论】字符串接龙(Python)
题目描述 题目链接:110. 字符串接龙 代码实现 import collectionsn int(input()) beginStr, endStr input().split() strList [input() for _ in range(n)]deque collections.deque() # 使用队列遍历结点 deque.append([beginStr, 1]) # 存储当前字符串和遍…...
车载以太网-TLS
文章目录 车载以太网与TLS的技术背景核心定位车载以太网TLS的技术架构车载TLS的核心安全机制TLS报文结构详解TLS工作机制密钥交换与计算流程标题完整握手流程(1-RTT)数据传输加密流程车载TLS的独特优化策略车载TLS的安全威胁相关标准车载以太网TLS(Transport Layer Security…...
