Lurk:面向网络社区的 Material 3 Android 客户端
Lurk:用 Flutter 打造一款更顺手的网络社区客户端
最近完成了一款名为 Lurk 的 Android 客户端项目。
它的出发点很简单:我希望把网络社区中真正需要的内容浏览、版块切换、帖子阅读和账号操作集中到一个更清晰的移动端界面里。在保留官方服务数据和账号能力的前提下,Lurk 更强调 Material 3 的视觉层级、连续的阅读体验,以及那些容易被忽略的交互细节。
项目基于 Flutter 开发,面向 Android 移动端,并通过统一网络层连接官方服务。客户端本身不提供独立的内容云服务,登录后的收藏、关注、发帖和互动仍然以官方账号与官方返回结果为准。
GitHub 项目地址:https://github.com/Chengeeker/Lurk
一、项目简介
Lurk 是一个面向 Android 的第三方网络社区客户端。
项目目前的重点包括:
- 使用官方数据源读取内容;
- 使用官方账号完成需要登录的操作;
- 用 Material 3 重新组织信息层级;
- 把长列表、图片阅读和详情页交互做得更连贯;
- 在网络失败时保留合理的本地缓存与重试能力。
二、为什么要重新做一个客户端?
网络社区的内容本身并不复杂,但移动端的使用体验很容易被一些细节打断:
- 关注的版块较多时,列表可能只显示服务端默认返回的一页;
- 公告或版规如果使用静态占位文本,用户看到的内容就可能和实际版块不一致;
- 收藏如果只写入手机本地,换设备或使用官方客户端时就无法看到;
- 帖子详情页的顶部操作过多,会影响标题、正文和回复之间的阅读关系;
- 图片需要查看原图或放大时,双击、拖拽和左右切换必须同时保持可用;
- 网络暂时失败时,应该清楚区分“本地已保存”和“官方服务已同步”。
Lurk 的开发重点,就是把这些问题从界面一路追溯到网络请求、登录状态和本地缓存,而不是只给某个按钮增加视觉反馈。
三、核心技术栈
项目整体技术栈比较直接:
| 技术 | 用途 |
|---|---|
| Flutter | Android UI 与业务开发框架 |
| Dart | 主要开发语言 |
| Material 3 | UI 设计体系 |
| Riverpod | 状态管理与页面状态同步 |
| Dio | 网络请求与统一客户端封装 |
| WebView | 网页授权与内置网页浏览 |
| flutter_secure_storage | 登录会话的安全存储 |
| SharedPreferences | 非敏感配置与本地缓存 |
| Extended Image | 高清图片、双击缩放与图片画廊 |
| video_player | 视频内容播放 |
| package_info_plus | 应用版本信息读取 |
| Android 原生 API | 媒体保存、权限与系统能力衔接 |
代码按职责拆分为核心层和功能模块:
1 | lib/ |
网络请求、认证、存储和具体页面各自保持边界,后续排查“显示内容不正确”时,可以分别确认服务端响应、模型解析、状态更新和 UI 渲染,而不需要在一个页面文件里追踪所有逻辑。
四、首页信息流与版块列表
首页提供多种内容入口,包括关注内容、推荐内容和热门内容。列表使用统一的卡片模型渲染文字、头像、图片、视频和互动信息,并支持下拉刷新与继续加载。
“进吧”一类的版块入口并不是固定写在本地的示例数据。登录后,客户端会从官方服务读取账号实际关注的版块,并处理分页、嵌套响应、重复项和不同返回结构。这样即使用户关注的版块数量较多,新关注的版块也不会因为只读取服务端第一组数据而被首页隐藏。
版块页面还会根据实际返回的版块信息显示头像、名称、帖子列表和互动状态。相关内容由网络层读取后再交给页面渲染,页面不会用一组静态文本冒充真实公告或版规。
五、Material 3 与界面设计
Lurk 的界面以 Material 3 为基础,同时加入了一些更适合长时间阅读的移动端表现形式。
1. 主题与个性化
应用支持浅色、深色和纯黑显示,并保留系统动态取色以及预设主题选项。设置页中的个性化选项会通过状态管理层驱动列表、详情和弹窗,避免不同页面各自保存一套互相不一致的配置。
目前可以调整的内容包括:
- 字体与字体粗细;
- 刷新率偏好;
- 图片加载策略;
- 自动加载下一页;
- 版块默认排序;
- 是否记录浏览历史;
- 内置浏览器开关;
- 屏蔽词与内容过滤。
2. 详情页顶部入口
帖子详情页的顶部中间使用胶囊样式的版块入口,左侧显示版块头像,右侧显示版块名称。点击后可以直接进入对应版块,减少了在详情页中寻找返回入口或额外菜单的步骤。
右上角只保留和当前帖子直接相关的操作:收藏,以及在确认当前账号确实拥有该帖时显示的删除入口。删除按钮与收藏按钮使用相同的图标按钮尺寸和布局,保持顶部操作的对齐关系。
六、帖子阅读、回复与图片浏览
详情页负责展示主帖、楼层回复和楼中楼内容,并提供刷新、继续加载、只看楼主、正序/倒序等阅读操作。
互动能力包括:
- 发表评论和回复;
- 表情输入;
- 复制文字;
- 查看楼中楼;
- 点赞与取消点赞;
- 收藏与取消收藏;
- 删除当前账号发布的帖子或回复。
高清图片画廊
点击图片后进入独立的全屏画廊,支持:
- 双指缩放;
- 双击放大与还原;
- 图片拖拽;
- 多图左右切换;
- 加载失败后重新尝试;
- 保存图片到系统媒体库。
图片手势需要同时处理缩放和页面切换。Lurk 使用专门的手势图片组件,并把图片页的滚动物理、缩放范围和双击倍率统一配置,降低左右滑动时无响应或误触发缩放的概率。
七、收藏与官方云端同步
收藏功能区分了“官方云端状态”和“本地缓存状态”。
登录后,客户端会从官方服务分页读取当前账号的收藏列表;在收藏或取消收藏时,也会调用对应的官方操作接口。手机本地只负责缓存列表、维持页面即时反馈,以及在短暂网络失败时记录待同步操作。
当请求暂时失败时,界面会明确提示当前操作是已经同步到云端,还是仅暂存于本地并等待重试。下一次进入收藏页或恢复网络后,客户端会重新读取官方列表,并处理之前尚未成功提交的变更。
未登录时,应用仍然可以提供本地收藏,但这类收藏只属于当前设备和当前本地数据,不会被误认为已经写入官方账号。这样可以避免把“本地保存成功”错误显示成“云端同步成功”。
八、登录与网络层
登录模块支持网页授权和凭据导入两种路径。敏感的登录会话优先保存在系统安全存储中,普通配置备份不会包含完整账号凭据。
统一网络层主要负责:
- 请求头和会话信息处理;
- 接口签名与必要参数整理;
- 登录状态与访问令牌检查;
- 响应结构解析;
- 错误信息向页面传递;
- 需要时有限次数地刷新登录校验信息;
- 网络失败后的本地缓存与待重试操作。
网络请求不会因为鉴权失败而无限重试。遇到登录状态失效时,客户端会把结果交给上层页面,让用户重新授权或检查账号状态。
九、设置、历史与内容过滤
设置页集中管理主题、显示习惯、媒体保存路径、浏览历史和内容屏蔽。
内容过滤采用用户可编辑的屏蔽词列表。启用后,匹配到的内容会直接从列表中隐藏,不使用空白卡片或无意义的占位内容填充原来的位置。历史记录则可以按需要关闭,并提供清理入口。
应用版本信息使用构建配置作为唯一来源,设置首页和“关于 Lurk”详情页显示同一组版本名与构建号,避免出现页面之间版本信息不一致的问题。
十、项目构建
项目使用 Flutter 构建 Android Release 安装包。
获取依赖:
1 | flutter pub get |
运行测试:
1 | flutter test |
构建 Release APK:
1 | flutter build apk --release --target-platform android-arm64 --android-skip-build-dependency-validation |
当前构建产物使用版本名 1.6.1 和构建号 11。版本命名遵循语义化规则:功能更新增加次版本号,问题修复增加补丁号;每次发布 Android 构建号正常递增。
十一、开源与项目定位
Lurk 目前以开源项目的形式发布。
它不是一个新的内容平台,也不试图建立独立的账号体系或内容云服务。更准确地说,Lurk 是一次围绕以下问题进行的 Flutter Android 工程实践:
- 如何把官方服务数据可靠地转换为移动端可读的内容;
- 如何让登录、云端收藏和本地缓存保持清晰的边界;
- 如何使用 Material 3 组织一个长列表内容应用;
- 如何在图片、回复、版块切换和帖子操作之间保持连续的交互反馈。
如果你对 Flutter、Material 3、Android 客户端开发、网络接口适配或内容阅读产品设计感兴趣,可以直接查看项目源码:
GitHub: https://github.com/Chengeeker/Lurk
结语
Lurk 从一开始就不是一个只展示页面的 UI Demo。
从首页信息流和版块分页,到真实公告读取;从官方云端收藏,到本地失败重试;从详情页的胶囊入口,到图片双击缩放和左右切换,这个项目覆盖了一个移动客户端从网络层、数据模型到交互层的完整链路。
对我来说,这个项目最有价值的地方,是不断验证一个很实际的问题:
当一个客户端需要连接真实的官方服务时,怎样才能让每个按钮、每条提示和每个列表项都对应真实的状态变化?
这也是 Lurk 后续继续迭代的方向。






