资讯动态

Android SQLite备忘录应用开发全解析

发布时间:2026/10/28 5:24:48 来源:尧图企业网站定制
1. 项目概述Android Studio开发的SQLite备忘录应用这个纯安卓项目是一个基于本地数据库的记事本应用核心功能包括创建、编辑、删除备忘录条目所有数据都存储在设备本地的SQLite数据库中。作为Android开发入门到进阶的经典练手项目它涵盖了以下关键技术点Android基础组件Activity、RecyclerView等的使用SQLite数据库的CRUD操作实现Material Design基础界面设计数据持久化方案选型与实践我在实际开发中发现这类看似简单的应用其实藏着不少值得深挖的技术细节。比如SQLite数据库版本迁移的处理、列表数据的局部刷新优化、以及如何平衡内存占用与查询效率等。接下来我会结合具体代码拆解这个项目的完整实现过程。2. 开发环境与项目搭建2.1 Android Studio配置要点建议使用最新稳定版Android Studio当前为Giraffe 2022.3.1配置时特别注意JDK版本使用JDK 17Android Studio内置版本即可Gradle插件7.4以上版本build.gradle关键配置android { compileSdk 33 defaultConfig { minSdk 23 targetSdk 33 } } dependencies { implementation androidx.core:core-ktx:1.10.1 implementation androidx.appcompat:appcompat:1.6.1 implementation com.google.android.material:material:1.9.0 }注意避免使用过时的Support库全部迁移到AndroidX组件2.2 项目结构设计采用清晰的模块化结构app/ ├── java/ │ ├── com.example.notepad/ │ │ ├── activities/ # 界面相关 │ │ ├── adapters/ # 列表适配器 │ │ ├── database/ # 数据库操作 │ │ └── models/ # 数据模型 └── res/ ├── layout/ # 界面布局 ├── values/ # 资源文件 └── menu/ # 选项菜单这种结构虽然简单但为后续功能扩展预留了空间。我在多个项目中验证过这种组织方式在中小型应用中最具可维护性。3. 数据库层实现详解3.1 SQLiteOpenHelper定制核心数据库操作类NoteDatabaseHelper.ktclass NoteDatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { companion object { private const val DATABASE_NAME notes.db private const val DATABASE_VERSION 1 const val TABLE_NOTES notes const val COLUMN_ID _id const val COLUMN_TITLE title const val COLUMN_CONTENT content const val COLUMN_CREATED created_at const val COLUMN_UPDATED updated_at } override fun onCreate(db: SQLiteDatabase) { val createTable CREATE TABLE $TABLE_NOTES ( $COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COLUMN_TITLE TEXT NOT NULL, $COLUMN_CONTENT TEXT, $COLUMN_CREATED TEXT DEFAULT CURRENT_TIMESTAMP, $COLUMN_UPDATED TEXT DEFAULT CURRENT_TIMESTAMP ) .trimIndent() db.execSQL(createTable) } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { // 实际项目中需要处理数据库迁移逻辑 db.execSQL(DROP TABLE IF EXISTS $TABLE_NOTES) onCreate(db) } }关键设计考量使用AUTOINCREMENT主键确保唯一性记录创建和更新时间戳便于排序预留onUpgrade方法应对未来架构变更3.2 数据访问对象(DAO)模式实现创建NoteDao.kt封装CRUD操作class NoteDao(private val dbHelper: NoteDatabaseHelper) { fun insertNote(note: Note): Long { val db dbHelper.writableDatabase val values ContentValues().apply { put(NoteDatabaseHelper.COLUMN_TITLE, note.title) put(NoteDatabaseHelper.COLUMN_CONTENT, note.content) } return db.insert(NoteDatabaseHelper.TABLE_NOTES, null, values) } fun updateNote(note: Note): Int { val db dbHelper.writableDatabase val values ContentValues().apply { put(NoteDatabaseHelper.COLUMN_TITLE, note.title) put(NoteDatabaseHelper.COLUMN_CONTENT, note.content) put(NoteDatabaseHelper.COLUMN_UPDATED, SimpleDateFormat(yyyy-MM-dd HH:mm:ss, Locale.getDefault()) .format(Date())) } return db.update( NoteDatabaseHelper.TABLE_NOTES, values, ${NoteDatabaseHelper.COLUMN_ID} ?, arrayOf(note.id.toString()) ) } // 其他方法deleteNote(), getNoteById(), getAllNotes()等 }实战经验ContentValues比直接拼接SQL更安全能有效防止SQL注入4. 用户界面设计与实现4.1 主界面笔记列表使用RecyclerView实现高性能滚动列表!-- res/layout/activity_main.xml -- androidx.recyclerview.widget.RecyclerView android:idid/notesRecyclerView android:layout_widthmatch_parent android:layout_heightmatch_parent app:layoutManagerandroidx.recyclerview.widget.LinearLayoutManager tools:listitemlayout/item_note /列表项布局item_note.xml采用Material Card设计com.google.android.material.card.MaterialCardView android:layout_widthmatch_parent android:layout_heightwrap_content app:cardElevation2dp app:cardCornerRadius8dp LinearLayout android:orientationvertical android:padding16dp TextView android:idid/titleTextView android:textAppearance?attr/textAppearanceHeadline6 tools:text示例标题/ TextView android:idid/contentTextView android:maxLines2 android:ellipsizeend tools:text这里是笔记内容的预览.../ TextView android:idid/timeTextView android:textAppearance?attr/textAppearanceCaption tools:text2023-07-20/ /LinearLayout /com.google.android.material.card.MaterialCardView4.2 笔记编辑界面采用经典的标题内容布局ScrollView android:layout_widthmatch_parent android:layout_heightmatch_parent LinearLayout android:orientationvertical android:padding16dp com.google.android.material.textfield.TextInputLayout stylestyle/Widget.MaterialComponents.TextInputLayout.OutlinedBox android:hint标题 com.google.android.material.textfield.TextInputEditText android:idid/titleEditText android:maxLines1 android:imeOptionsactionNext/ /com.google.android.material.textfield.TextInputLayout com.google.android.material.textfield.TextInputLayout stylestyle/Widget.MaterialComponents.TextInputLayout.OutlinedBox android:hint内容 com.google.android.material.textfield.TextInputEditText android:idid/contentEditText android:minLines5 android:gravitytop/ /com.google.android.material.textfield.TextInputLayout /LinearLayout /ScrollView5. 功能逻辑实现5.1 列表数据加载优化在MainActivity中实现高效数据加载class MainActivity : AppCompatActivity() { private lateinit var notesRecyclerView: RecyclerView private lateinit var adapter: NotesAdapter private val noteDao by lazy { NoteDao(NoteDatabaseHelper(this)) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupRecyclerView() loadNotes() } private fun setupRecyclerView() { notesRecyclerView findViewById(R.id.notesRecyclerView) adapter NotesAdapter { note - // 点击项处理 startActivity(EditNoteActivity.newIntent(this, note.id)) } notesRecyclerView.adapter adapter } private fun loadNotes() { lifecycleScope.launch(Dispatchers.IO) { val notes noteDao.getAllNotes().sortedByDescending { it.updatedAt } withContext(Dispatchers.Main) { adapter.submitList(notes) } } } }关键优化点使用lifecycleScope管理协程生命周期IO操作在后台线程执行数据按更新时间降序排列5.2 笔记保存逻辑EditNoteActivity中的保存实现private fun saveNote() { val title titleEditText.text.toString().trim() if (title.isEmpty()) { showError(标题不能为空) return } val note currentNote?.copy( title title, content contentEditText.text.toString(), updatedAt Date() ) ?: Note( title title, content contentEditText.text.toString() ) lifecycleScope.launch(Dispatchers.IO) { try { if (currentNote null) { noteDao.insertNote(note) } else { noteDao.updateNote(note) } withContext(Dispatchers.Main) { setResult(RESULT_OK) finish() } } catch (e: Exception) { withContext(Dispatchers.Main) { showError(保存失败: ${e.message}) } } } }6. 性能优化与调试技巧6.1 数据库查询优化索引优化为常用查询字段添加索引override fun onCreate(db: SQLiteDatabase) { // ... 建表语句之后 db.execSQL(CREATE INDEX idx_notes_updated ON notes(updated_at)) }分页加载避免一次性加载全部数据fun getNotesPaginated(offset: Int, limit: Int): ListNote { val db dbHelper.readableDatabase val cursor db.query( TABLE_NOTES, null, null, null, null, null, $COLUMN_UPDATED DESC, $offset,$limit ) // ... 解析cursor为Note对象列表 }6.2 常见问题排查数据库锁定问题现象并发操作时报database is locked解决方案确保每次操作后关闭Cursor和Database连接列表刷新不及时现象新增/修改数据后列表未更新解决方案使用DiffUtil智能刷新class NotesDiffCallback : DiffUtil.ItemCallbackNote() { override fun areItemsTheSame(oldItem: Note, newItem: Note) oldItem.id newItem.id override fun areContentsTheSame(oldItem: Note, newItem: Note) oldItem newItem } // 在Adapter中使用 val diffResult DiffUtil.calculateDiff(NotesDiffCallback(oldList, newList)) diffResult.dispatchUpdatesTo(this)7. 项目扩展方向数据同步功能添加Firebase实现云端备份使用WorkManager定期同步富文本支持集成Markdown编辑器添加图片附件功能分类与标签扩展数据库结构支持多分类实现标签云功能回收站机制软删除代替物理删除定期自动清理这个备忘录项目虽然基础但涵盖了Android开发的多个核心知识点。我在实际开发中最大的体会是良好的架构设计比急着写功能代码更重要。特别是在数据持久化方面前期花时间设计合理的数据库结构后期能省去大量重构时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑