ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

web-to-app 应用分类机制:从标签行操作到 Room 持久化的完整解析

web-to-app 应用分类机制:从标签行操作到 Room 持久化的完整解析 web-to-app 应用分类机制从标签行操作到 Room 持久化的完整解析【免费下载链接】web-to-appThe most full featured web-to-app toolkit on Android, a complete APK workshop that runs entirely on your phone项目地址: https://gitcode.com/GitHub_Trending/web/web-to-app在 web-to-app一个完全运行在手机上、功能齐全的 web-to-app 工具集中「我的应用」页面顶栏下方的标签行提供了应用分类功能你可以为应用建立自定义分类、按分类过滤列表并把应用在不同分类间移动。本文以分类功能的实际使用方式为主线结合仓库中的数据模型、DAO 与 UI 源码讲清分类是如何被创建、过滤、排序和持久化的帮助你在管理大量自建 APK 项目时理解这一整理机制的完整行为。分类标签行的构成我的应用页面顶栏下方的标签行由三部分组成见 CategoryComponents.kt 中的CategoryTabRow全部All固定标签selectedCategoryId null时高亮点击后展示所有应用未分类Uncategorized固定标签选中值为-1L过滤出categoryId为空的 application自定义分类每个分类渲染为一个带图标的 Chip图标通过 SvgIconMapper 把分类存储的图标名称映射为矢量图标 添加按钮和末尾的管理分类Tune 图标按钮分别打开分类编辑对话框与批量管理对话框。整行基于LazyRow横向滚动实现各 Chip 间距 6dp支持长按分类标签唤出快捷菜单。基本操作筛选、添加、编辑、删除选中分类进行筛选选中某个标签即把应用列表过滤到该分类。过滤逻辑集中在 MainViewModel.kt 中filtered when (categoryId) { null - filtered // 全部 -1L - filtered.filter { it.categoryId null } // 未分类 else - filtered.filter { it.categoryId categoryId } // 指定分类 }即分类筛选是一个三态判断null表示全部-1L表示未分类其余值为具体分类 id。应用总数在几十上百量级时这一行标签就相当于一层低成本的索引。添加分类点击 操作弹出CategoryEditorDialogCategoryComponents.kt需要给它一个名称和一个图标名称输入框PremiumTextField为空时保存按钮不可用即空名称无法创建分类图标不是自由上传而是从 6 组内置预设图标中选择常用folder、star、heart、fire、lightbulb、auto_awesome、媒体、工作学习、生活出行、工具、娱乐共 36 个 Material 风格图标新建时默认为folder。保存后进入 MainViewModel.addCategoryval category AppCategory( name name, icon icon, sortOrder categories.value.size // 新分类追加到行尾 ) categoryRepository.createCategory(category)从源码结构看新分类的sortOrder被设为当前分类总数因此它会出现在标签行末尾。编辑现有分类长按分类标签唤出下拉菜单其中包含编辑与删除以及上移/下移两个排序项首尾位置对应方向自动禁用。编辑复用CategoryEditorDialog传入已有分类作为初始值可改名或换图标走updateCategory→AppCategoryDao.update。除标签行长按菜单外行尾的 Tune 按钮打开CategoryManageDialogCategoryComponents.kt在一个对话框里集中完成上移、下移、编辑、删除适合分类较多时批量整理。删除分类删除需二次确认deleteCategoryConfirm文案的WtaAlertDialog。确认后的级联处理见 MainViewModel.deleteCategory调用repository.clearCategoryId(category.id)把该分类下所有应用的categoryId置空——这些应用会落入「未分类」而不是报错或丢失再删除分类记录本身若当前筛选正停在这个分类上选中态回退到「全部」。对应的数据库语句在 WebAppDao.ktQuery(UPDATE web_apps SET categoryId NULL WHERE categoryId :categoryId) suspend fun clearCategoryId(categoryId: Long)在分类间移动应用应用的分类从它的操作菜单更改点击应用卡片上的 ⋮再点移动到分类选择目标详见 移动到分类。对话框MoveToCategoryDialogCategoryComponents.kt列出「未分类」加所有自定义分类应用当前所在分类会带勾选标记选中目标后应用立即移动、列表即时重新过滤。底层实现在 MainViewModel.moveAppToCategory即把webApp.categoryId改为目标值后调用updateWebApp一次主键更新完成。数据模型与持久化分类实体分类是一个 Room 实体AppCategory.ktEntity(tableName app_categories) data class AppCategory( PrimaryKey(autoGenerate true) val id: Long 0, val name: String, val icon: String , val color: String #6200EE, val sortOrder: Int 0, val createdAt: Long System.currentTimeMillis() )字段说明字段说明id自增主键应用表与分类的关联键name分类名称必填icon图标标识预设图标名或 emoji默认color预留的颜色字段默认#6200EEsortOrder标签行排序依据可上移/下移调整createdAt创建时间戳作为同sortOrder下的次级排序键应用侧的关联与索引应用表web_apps中带一个可空的categoryId列并建立了索引以加速按分类查询见 AppDatabase.ktcategoryId INTEGER, CREATE INDEX IF NOT EXISTS index_web_apps_categoryId ON web_apps(categoryId)该列在 14→15 版本迁移中通过ALTER TABLE web_apps ADD COLUMN categoryId INTEGER DEFAULT NULL加入AppDatabase.kt老版本升级上来的应用categoryId均为空自然归入「未分类」。读取与写入链路分类的读写链路为 DAO → Repository → ViewModelAppCategoryDao.kt、AppCategoryRepository.ktgetAllCategories()返回FlowListAppCategory按sortOrder ASC, createdAt ASC排序任何增删改都会经 Room 的 Flow 机制自动驱动标签行刷新无需手动通知 UIinsert使用OnConflictStrategy.REPLACE并返回新行 id排序调整上移/下移的实现是交换两个分类的sortOrder后逐条updateMainViewModel.moveCategory与getAllCategories的排序规则对应。筛选状态的持久化「上次停在哪个分类」由 CategoryFilterStore 负责它独立于 Room用 SharedPreferences键名home_category_filter保存class CategoryFilterStore(context: Context) { var rememberEnabled: Boolean // 默认 true fun loadSelection(): Long? // null 表示「全部」/无记录 fun saveSelection(categoryId: Long?) }设计上有三个值得注意的细节三态编码全部编码为Long.MIN_VALUE读出时转为null未分类编码为-1与 UI 侧一致其余为真实分类 id键缺失全新安装或记录被清除也按「全部」处理remember 开关只控制冷启动恢复源码注释明确说明选中值每次都会写入开关只在应用启动时决定是否恢复上次筛选所以后来打开开关仍能恢复当前选择悬空 id 兜底冷启动恢复时MainViewModel 初始化若保存的分类 id 对应记录已被删除则回退到「全部」不会卡在无效筛选上。每次点击标签selectCategory都会同步执行_selectedCategoryId.value categoryId与categoryFilterStore.saveSelection(categoryId)保证内存态与磁盘态一致。创建应用时自动继承当前分类一个文档未提及但源码确认的行为从源码结构看在「我的应用」页选择某个分类后再创建新应用该应用会自动归入当前选中的分类。MainViewModel 中各类型Media、HTML、WordPress、Node.js、PHP、Python、Go、Multi-Site 等的统一创建入口都有val categoryId _selectedCategoryId.value?.takeIf { it 0 }即仅当筛选停在某个真实分类id 0时才继承停在「全部」或「未分类」时不继承新应用默认未分类。这使「先选分类、再批量建应用」成为一条顺畅的操作路径。分类的定位纯整理不影响构建与运行与移动分类文档一致分类纯粹用于整理——移动或归类应用不改变它如何构建或运行。从实现上可以印证这一点categoryId只出现在web_apps表的查询与筛选路径中应用的appType、构建参数等字段与之完全解耦分类数据也不参与 APK 导出流程。它解决的是「手机上管理几十个自封装 web 项目时如何快速找到目标」的问题而非任何运行时语义。【免费下载链接】web-to-appThe most full featured web-to-app toolkit on Android, a complete APK workshop that runs entirely on your phone项目地址: https://gitcode.com/GitHub_Trending/web/web-to-app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表