Android数据库开发——SQLite

简介: 上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中。

上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中。后来在智能手机、平板流行之后,它作为文件型数据库,几乎成为了智能设备单机数据库的必选,可以随着安卓app打包到apk文件当中。

SQLite的官方网站是http://www.sqlite.org/,可以任意下载,上面也有详尽的文档可以参考,这篇博客重点关注SQLite在Android开发中如何使用。

在Android开发中,推荐建立一个类继承自SQLiteOpenHelper来创建数据库操作类,比如:

public class DBHelper extends SQLiteOpenHelper {

	private static final String database = "test.db";
	private static final Integer version = 1;

	public DBHelper(Context context) {

		// 构造函数初始化各成员变量
		super(context, database, null, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {

		// 当通过SQLiteOpenHelper的子类获取数据库连接时,如果数据库不存在,则调用onCreate方法来创建数据库
		String sql = "create table Score(id integer primary key autoincrement,name varchar(20),point integer)";
		db.execSQL(sql);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// 当传入的实例的数据库版本号高于之前的版本号时,系统会自动调用onUpgrade方法更新数据库
		// 更新数据库的操作:备份数据库表数据,重新创建或修改表、约束等,然后将原来的数据导入到新建的表中。

	}
}
上面的代码有3点需要注意:

1、构造函数(方法)中指定了数据库的名称和版本号

它会默认的在data/data/包名/databases/目录下创建这个数据库,当然你也可以指定数据库文件存在的路径;版本号设置为1,如果你要想升级,可以在构造方法的参数中加上version,以便初始化。


2、onCreate是在数据库文件没有创建的时候执行,如果有了的话则不执行

3、onUpgrade是在新的指定版本号高于旧的指定版本号的时候执行,一般在数据库升级的时候需要操作

然后我们建一个具体的数据库操作类:

/**
 * 成绩操作类
 * 
 * @author guwei
 * 
 */
public class ScoreOp {

	// 插入一条成绩记录
	public long insert(SQLiteDatabase db, String name, Integer point) {
		try {
			db.beginTransaction();
			ContentValues values = new ContentValues();
			values.put("name", name);
			values.put("point", point);
			long result = db.insert("Score", null, values);
			if (result != -1) {
				db.setTransactionSuccessful();
			}
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 修改一条成绩记录
	public int update(SQLiteDatabase db, String name, Integer point) {
		try {
			db.beginTransaction();
			ContentValues values = new ContentValues();
			values.put("name", name);
			values.put("point", point);
			int result = db.update("Score", values, "name = ?",
					new String[] { name });
			db.setTransactionSuccessful();
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 删除一条成绩记录
	public long delete(SQLiteDatabase db, String name) {
		try {
			db.beginTransaction();
			int result = db.delete("Score", "name = ?", new String[] { name });
			db.setTransactionSuccessful();
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 查询根据name正向排序的前10条总分大于指定分数的人员信息
	public Cursor query(SQLiteDatabase db, Integer point) {
		return db.query("Score",
				new String[] { "name", "sum(point) as points" }, null, null,
				"name", "sum(point)>=" + point, "name asc", "0,10");
	}

	// 更灵活的查询,SQL任意拼接
	public Cursor query(SQLiteDatabase db, String sql, String[] selectionArgs) {
		return db.rawQuery(sql, selectionArgs);
	}
}
这上面封装了CRUD操作,而且都是带事务的(执行多条SQL时需要),值得关注的是最后的两个query方法。

第一个query是指定了一个复杂sql查询语句的情况。

按照顺序,参数的含义如下:

1)、table The table name to compile the query against.   

指定的查询的表名

2)、columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.

返回的查询列表的列名

3)、selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.

where条件,不包括where关键字

4)、selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.

where条件指定的参数值

5)、groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.

group by分组后面跟着的列名

6)、having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
having 后面紧跟着的在分组基础上进一步筛选的内容

7)、orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.

order by后面根据某字段排序

8)、limit Limits the number of rows returned by the query, formatted as LIMIT clause. Passing null denotes no LIMIT clause.
limit关键字,分页查询时使用

实际上上面对应的这8个参数,就是对应如下SQL查询语句各关键字后面的内容,其原理就是通过指定参数拼接如下SQL语句。

这里顺便提一下,SQLite Expert是非常好用的管理SQLite数据库的工具,可以在http://www.sqliteexpert.com/下载到,也可以直接搜索下载相应破解版本。

回到第二个query方法,参数很简单,只有一个sql语句以及一个string数组(提供sql语句参数的值)。这个方法的意义就在于它很灵活,可以直接把能够执行的sql扔进去执行,而且是参数化的,是第一种查询方法很有力的补充。

好,最后我们就可以写测试代码来验证了。界面很简单,直接放置一个按钮即可。

public class SQLiteActivity extends Activity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_sqlite);  
  
        Button btn = (Button) findViewById(R.id.btn);  
        btn.setOnClickListener(new View.OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                DBHelper dbHelper = new DBHelper(SQLiteActivity.this);  
                  
                //获得一个可写数据库操作对象  
                SQLiteDatabase wdb = dbHelper.getWritableDatabase();  
                  
                //添加纪录  
                ScoreOp scoreOp = new ScoreOp();  
                scoreOp.insert(wdb, "zhang3", 98);  
                scoreOp.insert(wdb, "zhang3", 94);  
  
                scoreOp.insert(wdb, "li4", 92);  
                scoreOp.insert(wdb, "wang5", 89);  
                scoreOp.insert(wdb, "wang5", 82);  
  
                //修改记录  
                scoreOp.update(wdb, "li4", 90);  
  
                //删除记录  
                scoreOp.delete(wdb, "li4");  
  
                //获得一个可读数据库操作对象  
                SQLiteDatabase rdb = dbHelper.getReadableDatabase();  
                  
                // 1.可以调用系统提供的query方法,以指定参数的形式返回Cursor对象  
                // Cursor cursor = scoreOp.query(rdb, 192);  
  
                // 2.可以直接执行SQL查询语句  
                Cursor cursor = scoreOp  
                        .query(rdb,  
                                "select name,sum(point) as points from Score group by name having sum(point)>=192 order by name asc limit ?,?",  
                                new String[] { "0", "10" });  
                while (cursor.moveToNext()) {  
                    String name = cursor.getString(cursor  
                            .getColumnIndex("name"));  
                    Integer points = cursor.getInt(cursor  
                            .getColumnIndex("points"));  
  
                    Toast.makeText(SQLiteActivity.this,  
                            "姓名:" + name + ";总分:" + points, Toast.LENGTH_SHORT)  
                            .show();  
                }  
                cursor.close();  
            }  
        });  
  
    }  
  
}  


点击按钮执行之后就可以弹出符合条件的数据。如果不放心,可以切换到DDMS界面,选择File Explorer选项卡,找到路径下的我们创建的test.db文件,Pull(拉取)到电脑磁盘上,用SQLite Expert等工具打开验证。




目录
相关文章
|
5天前
|
存储 安全 Android开发
安卓应用开发:构建一个高效的用户登录系统
【5月更文挑战第3天】在移动应用开发中,用户登录系统的设计与实现是至关重要的一环。对于安卓平台而言,一个高效、安全且用户体验友好的登录系统能够显著提升应用的用户留存率和市场竞争力。本文将探讨在安卓平台上实现用户登录系统的最佳实践,包括对最新身份验证技术的应用、安全性考量以及性能优化策略。
|
8天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
1天前
|
Android开发 Kotlin
Kotlin开发Android之基础问题记录
Kotlin开发Android之基础问题记录
11 1
|
1天前
|
Java Android开发
Android开发@IntDef完美替代Enum
Android开发@IntDef完美替代Enum
9 0
|
2天前
|
Android开发
Android 盒子开发过程中遇到的问题及解决方法
Android 盒子开发过程中遇到的问题及解决方法
7 2
|
2天前
|
机器学习/深度学习 算法 Android开发
安卓应用开发:打造高效通知管理系统
【5月更文挑战第6天】 在现代移动应用的海洋中,用户经常面临信息过载的挑战。一个精心设计的通知管理系统对于提升用户体验至关重要。本文将探讨在安卓平台上如何实现一个高效的通知管理系统,包括最佳实践、系统架构设计以及性能优化技巧。通过分析安卓通知渠道和优先级设置,我们的目标是帮助开发者构建出既能吸引用户注意,又不会引发干扰的智能通知系统。
16 2
|
3天前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
8天前
|
存储 Java Android开发
安卓应用开发中的内存优化策略
【4月更文挑战第30天】在移动开发领域,尤其是安卓平台上,内存管理是影响应用性能和用户体验的关键因素。由于安卓设备的硬件资源有限,不合理的内存使用会导致应用响应缓慢、消耗过多电量甚至崩溃。本文将探讨针对安卓平台的内存优化技巧,旨在帮助开发者提高应用的性能和稳定性,从而提升用户满意度。我们将详细讨论内存泄漏的预防、合理的内存分配策略以及高效的内存回收方法。
|
9天前
|
机器学习/深度学习 安全 数据处理
构建未来:基于Android的智能家居控制系统开发
【4月更文挑战第29天】 随着物联网技术的蓬勃发展,智能家居已成为现代技术革新的重要领域。本文将深入探讨基于Android平台的智能家居控制系统的设计和实现,旨在提供一种用户友好、高度集成且功能丰富的解决方案。通过利用Android设备的广泛普及和其强大的处理能力,结合最新的无线通讯技术和人工智能算法,我们旨在打造一个可靠、易用且具有高度可定制性的智能家居控制环境。文中不仅详细阐述了系统架构、关键技术选型以及界面设计,还对可能遇到的安全挑战进行了分析,并提出了相应的解决策略。
|
9天前
|
监控 Java Android开发
安卓应用开发中的内存优化策略
【4月更文挑战第29天】在面对安卓设备多样化的硬件配置时,合理管理应用内存成为提升用户体验的关键。本文深入探讨了安卓应用开发中常见的内存泄漏问题,并提出了一系列针对性的优化策略。通过分析内存分配机制、垃圾回收原理及内存监控工具的使用,揭示了高效内存管理的实践方法。文章旨在为开发者提供一套系统的内存优化解决方案,以实现更流畅、稳定的应用性能。