在 Android* 应用中使用数据库






4.73/5 (9投票s)
在本文中,我们将探讨 Android* SQLite API 以及用于数据库创建和维护的辅助类。
在移动应用程序中,使用 SQLite 等简单的数据库后端可以在各种用例中发挥作用。在本文中,我们将探讨 Android* SQLite API 以及用于数据库创建和维护的辅助类。我们将讨论如何创建和使用预填充数据库,并使用 SQLite 工具库为示例餐厅应用程序实现数据库后端。
目录
摘要
概述
一家零售餐饮企业样本应用 – Little Chef。
使用现有数据库
从餐厅数据库访问菜单项
摘要
概述
Android 内置了对 SQLite 数据库的支持。它支持 SQLite 的所有功能,并提供了一个具有一致接口的包装器 API。有关详细信息,请参阅以下链接。
https://developer.android.com.cn/guide/topics/data/data-storage.html#db
Android SQLite API 是通用的,它将数据库的创建、版本控制、升级以及其他自定义的数据库处理留给开发者实现。如果我们想使用预填充的 SQLite 数据库,则需要额外的配置。
以下培训指南详细介绍了如何使用标准的 Android SQLite API。
https://developer.android.com.cn/training/basics/data-storage/databases.html
直接使用 Android SQLite API 可能会产生大量样板代码。有几个 Android 工具库可以帮助简化此过程,它们提供了额外的功能,以便在 Android 应用程序中更轻松高效地使用 SQLite 数据库。
SQLiteAssetHelper 是一个在 Android 开发者社区中很受欢迎的库,其受欢迎程度基于使用量和开发者参与度。有关完整参考,请参阅以下网站。https://github.com/jgilfelt/android-sqlite-asset-helper
一家零售餐厅示例应用程序 – Little Chef。
我们将使用一个示例餐厅应用程序(Little Chef)来讨论 SQLite 数据库和 SQLiteAssetHelper 库的用法。
该应用程序允许用户浏览不同的菜单类别和选项。
餐厅应用程序可以由厨师或用户使用,以查看不同的菜单类别和项目。示例应用程序实现了滑动切换不同类别的手势,选择菜单项会显示其详细信息。
可以使用 SQLite 数据库来存储所有菜单类别和项目详情。在应用程序的未来版本中,我们可以扩展数据库以支持其他类型的应用程序数据——销售数据、忠诚度计划、每个用户的自定义设置等。
使用现有数据库
根据应用程序的要求,我们可能需要用初始数据集预填充应用程序。在本示例餐厅应用程序的情况下,预填充了基本的标准菜单类别和项目详情。
Android API(例如 SQLiteOpenHelper)可用于在数据库创建和初始化过程中填充初始数据集。但是,这并不总是最优的,尤其是在数据集很大的情况下。此外,不建议在主线程中使用某些 SQLiteOpenHelper 调用。用户可能会在启动时遇到较长的初始化和 UI 延迟,具体取决于设备功能。另一种方法是预填充数据库并将其打包作为应用程序资源的一部分。
对于餐厅示例应用程序,我们使用 Python 编程 API for SQLite 离线创建了一个 SQLite 数据库。也有 GUI 客户端,可以手动编辑或向 SQLite 数据库添加数据。正如 Android SQLite API 文档中所建议的,我们添加了一个名为“_id”的列,用于唯一标识每一行。这在实现内容提供者和适配器抽象时会很有用。
使用 Android SQLite API 从应用程序的 assets 文件夹访问 SQLite 数据库需要我们将数据库文件从 assets 文件夹复制到应用程序的数据库文件夹路径。支持数据库升级和版本控制会使这更加复杂。
对于餐厅示例应用程序,我们使用 SQLiteAssetHelper* 库来访问预填充的数据库,该数据库作为应用程序资源的一部分进行打包。有关详细的使用说明,请参阅 SQLiteAssetHelper 库的 README 文档。
https://github.com/jgilfelt/android-sqlite-asset-helper
我们在“assets”下创建了一个“databases”文件夹,并将预填充的“restaurant.sqlite”文件复制到了“databases”文件夹。有关实现细节,请参阅以下代码片段。
package com.example.restaurant; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import com.readystatesoftware.sqliteasset.SQLiteAssetHelper; /** * Database handler for restaurant app. */ public class RestaurantDatabase extends SQLiteAssetHelper { private static final String TAG = SQLiteAssetHelper.class.getSimpleName(); private static final String DATABASE_NAME = "restaurant.sqlite"; private static final int DATABASE_VERSION = 1; public interface TABLES { String MENU = "menu"; String USER = "user"; String CUSTOMER = "customer"; } public interface MenuColumns { String CATEGORY = "category"; String NAME = "name"; String DESCRIPTION = "description"; String NUTRITION = "nutrition"; String PRICE = "price"; String IMAGENAME = "imagename"; } public RestaurantDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } public Cursor getMenuItems() { SQLiteDatabase db = getReadableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(TABLES.MENU); Cursor c = qb.query(db, null, null, null, null, null, null); c.moveToFirst(); return c; } }
从餐厅数据库访问菜单项
在初始化时,SQLiteAssetHelper 会自动将预填充的餐厅数据库从 assets 文件夹复制到适当的数据库路径。后续调用将重用数据库实例,除非请求升级。前面的代码片段显示了 getMenuItems 方法,该方法返回数据库中所有菜单项的光标。
以下代码片段显示了创建数据库实例,并从光标解析菜单项。
mDb = new RestaurantDatabase(this); mMenuItems = new ArrayList<MenuItem>(); Set<String> categories = new HashSet<String>(); Cursor c = mDb.getMenuItems(); while (c.moveToNext()) { String category = c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.CATEGORY)); categories.add(category); MenuItem menuItem = new MenuItem(); menuItem.setCategory(category); menuItem.setName(c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.NAME))); menuItem.setDescription(c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.DESCRIPTION))); menuItem.setNutrition(c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.NUTRITION))); menuItem.setPrice(c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.PRICE))); menuItem.setImageName(c.getString(c.getColumnIndexOrThrow(RestaurantDatabase.MenuColumns.IMAGENAME))); mMenuItems.add(menuItem); } c.close(); mCategoryList = new ArrayList<String>(categories);
不建议在主线程中处理数据库访问。我们可以使用 SQLiteAssetHelper 添加额外的抽象,例如 Android 内容提供者接口。
根据应用程序的需求和用例,我们可以为餐厅示例应用程序添加更多功能,例如支持数据库升级、版本控制,甚至后端服务器支持。在服务器后端数据库实现的情况下,我们可以使用应用程序的本地 SQLite 数据库作为临时缓存并提供离线功能。
总结
本文讨论了在 Android 应用程序中使用 SQLite 数据库。文章讨论了 Android SQLite API 和辅助类。我们使用了一个示例餐厅应用程序来演示如何使用 SQLiteAssetHelper 库的预填充数据库。
关于作者
Ashok Emani 是 Intel 软件和服务部门的一名软件工程师。他目前从事 Intel® Atom™ 处理器规模的启用项目。
注意事项
本文档中的信息是根据英特尔产品提供的。本文档不授予任何明示或暗示的、通过禁止反悔或其他方式授予的知识产权许可。除英特尔此类产品的销售条款和条件外,英特尔不承担任何责任,并否认与英特尔产品的销售和/或使用相关的任何明示或暗示的保证,包括对特定用途的适用性、适销性或对任何专利、版权或其他知识产权的侵权的保证。
除非 Intel 书面同意,否则 Intel 产品不设计也不用于任何可能导致人员伤亡的应用程序。
英特尔可随时更改规格和产品描述,恕不另行通知。设计者不得依赖未标记为“保留”或“未定义”的任何特性或说明的缺失或特性。英特尔为将来定义这些内容而保留这些内容,并对因其未来更改而产生的任何冲突或不兼容性不承担任何责任。此处的信息如有更改,恕不另行通知。请勿基于此信息最终确定设计。
本文档中描述的产品可能包含已知为勘误的设计缺陷或错误,这可能导致产品偏离已发布的规范。当前的已表征勘误可应要求提供。
请联系您当地的英特尔销售办事处或您的经销商以获取最新的规范,并在下订单前进行咨询。
如果需要有订单号且本文档中引用的文件副本,或其他英特尔文献,请致电 1-800-548-4725,或访问:http://www.intel.com/design/literature.htm
性能测试中使用的软件和工作负载可能已针对英特尔微处理器进行了性能优化。性能测试,如 SYSmark* 和 MobileMark*,是使用特定的计算机系统、组件、软件、操作和功能测量的。对这些因素的任何更改都可能导致结果有所不同。您应查阅其他信息和性能测试,以协助您全面评估您打算购买的产品,包括该产品与其他产品结合使用时的性能。
本文档中重印的任何软件源代码均根据软件许可证提供,并且只能根据该许可证的条款使用或复制。