Review:用 Flutter 打造一款现代化信息流客户端

最近完成了一款名为 Review 的 Android 客户端项目。

它的出发点其实很简单:我希望把一个成熟信息流平台的核心内容消费体验重新设计一遍,在保留时间线、分组、搜索、评论、媒体浏览等基础能力的同时,把界面做得更加简洁,把交互做得更加细腻,并尽可能利用 Android 原生能力提升整体体验。

项目目前基于 Flutter 开发,采用 Material 3 设计体系,并针对 Android 移动端进行了较多原生能力适配。

Github 项目地址 : https://github.com/Chengeeker/Review

一、项目简介

Review 是一个面向 Android 的第三方信息流客户端。

与传统信息流应用相比,这个项目更强调三个方面:

  • 内容展示尽可能纯粹
  • 界面和交互高度可定制
  • Flutter 与 Android 原生能力结合

项目使用 Flutter 3.x / Dart 3.x 开发,状态管理采用 Riverpod,整体 UI 建立在 Material 3 之上。

目前主要面向 Android arm64-v8a 架构,项目配置的最低 Android SDK 为 24,目标 SDK 为 35。GitHub 仓库目前采用 MIT License。

二、为什么要重新做一个客户端?

这个项目并不是单纯为了“换一个界面”。

在实际使用信息流产品的过程中,我发现很多体验问题并不一定来自功能不足,而是来自信息密度、视觉层级和交互细节。

例如:

  • 内容和推荐内容混杂时,很难快速找到自己真正关注的信息;
  • 卡片样式通常缺少足够的自定义空间;
  • 图片、长图、动态图片和视频之间的浏览体验并不统一;
  • 搜索、热榜、用户主页等功能往往被分散在不同入口;
  • 一些细节交互,例如点击反馈、页面转场、列表滚动和图片缩放,会直接影响使用时的“顺滑感”。

因此,Review 更像是一次围绕“信息流客户端应该是什么样”的重新设计。

三、核心技术栈

项目整体技术栈比较直接:

技术 用途
Flutter 跨平台 UI 与业务开发框架
Dart 主要开发语言
Material 3 UI 设计体系
Riverpod 状态管理
Dio 网络请求与拦截
WebView / CookieManager 登录会话与网页环境衔接
SharedPreferences 本地配置持久化
Extended Image 高清图片、长图与手势浏览
video_player 视频及动态媒体播放
WebDAV 可选的配置备份与恢复
Android 原生 API 权限、定位、媒体库、Cookie 等系统能力

项目的代码结构也按照功能和职责进行了拆分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lib/
├── core/
│ ├── api/
│ ├── auth/
│ ├── constants/
│ ├── storage/
│ ├── theme/
│ └── utils/
├── features/
│ ├── auth/
│ ├── compose/
│ ├── detail/
│ ├── feed/
│ ├── home/
│ ├── profile/
│ ├── search/
│ └── settings/

这样的结构可以把网络层、认证、存储、主题以及具体业务页面尽量解耦,后续继续扩展功能时也比较容易定位代码。

四、信息流与分组系统

Review 最核心的部分仍然是信息流。

项目针对不同类型的信息流进行了独立的数据路由处理,例如:

  • 主时间线;
  • 用户自定义分组;
  • 特定关注分组;
  • 公共热门内容;
  • 同城内容;
  • 多种搜索结果流。

其中一个比较重要的设计思路,是尽可能让不同内容来源使用独立的数据处理逻辑,而不是简单地把所有内容混合到一个列表里。

对于分组系统,客户端会读取用户已有的分组,并在本地建立对应的展示和排序关系。用户还可以通过分组管理页面调整个人分组、默认分组以及热门频道。

顶部时间线标题本身也可以作为交互入口。点击后会展开分组面板,通过网格方式快速切换不同内容流。

五、Material 3 与个性化设计

Review 的视觉设计大量采用 Material 3,同时加入了一些更加偏向现代 Android 客户端的表现形式。

1. 动态取色

项目支持 Android 12+ 的系统动态取色,可以根据系统壁纸生成主题颜色。

同时也提供多组预设主题,并支持深色、浅色以及 OLED 纯黑模式。

2. 信息卡片自由调整

用户可以调整:

  • 卡片圆角与布局;
  • 字体大小;
  • 行高;
  • 时间显示方式;
  • 图片布局;
  • 图片圆角;
  • 链接颜色;
  • 发布设备信息;
  • 内容附加信息;
  • 菜单按钮位置。

这些配置会统一通过状态管理层驱动,从而保证列表和详情页面保持一致。

3. 悬浮胶囊导航

底部导航采用了偏 Material 3 Expressive 的悬浮胶囊形式。

它并不是简单地把传统 BottomNavigationBar 改个圆角,而是把导航栏作为一个独立的视觉层处理,并结合 SafeArea、阴影、圆角裁剪等方式,让它与内容区域保持更明确的层级关系。

六、图片、长图与动态媒体

媒体浏览是这个项目投入比较多精力的一部分。

高清图片画廊

点击图片后进入独立全屏画廊。

画廊支持:

  • 双指缩放;
  • 双击阶梯缩放;
  • 图片拖拽;
  • 长图浏览;
  • 原图保存;
  • 多图连续浏览。

页面转场没有使用过于复杂的几何动画,而是采用更稳定的淡入淡出方式,以减少图片尺寸变化造成的视觉跳变。

长图优化

对于高度明显大于宽度的长图,客户端会自动采用顶部对齐,并提高缩放上限。

同时,整个屏幕区域都可以响应手势,即使图片本身只占屏幕中央的一部分,用户依然可以在周围区域进行缩放和拖动。

双击缩放则采用动画控制器配合缓动曲线,在不同倍率之间平滑过渡。

动态图片

项目还针对动态图片数据进行了专门解析。

如果媒体数据同时包含静态封面和视频部分,客户端可以识别其动态媒体属性,在画廊中进行循环播放,并支持分别保存静态图片、动态媒体或全部内容。

七、搜索与热榜

搜索系统被设计成一个相对独立的功能模块。

搜索入口可以直接从主要信息流页面进入,输入关键词后会展示实时联想内容。

如果关键词对应用户,还可以直接展示用户卡片,并跳转到对应个人主页。

搜索结果则进一步划分为多个维度,例如:

  • 综合;
  • 实时;
  • 用户;
  • 图片;
  • 视频;
  • 关注;
  • 热门;
  • 评论;
  • 话题;
  • 地点;
  • 商品等。

不同排序方式也采用不同的计算逻辑。

例如综合排序会综合互动数据和内容信息进行排序,而实时排序更加注重发布时间。

此外,项目还提供独立的热榜大厅,并按照不同内容领域进行分类。

八、个人主页与媒体内容

个人主页采用三栏式结构:

  • 内容;
  • 相册;
  • 视频。

其中图片和动态媒体会按照不同类型进行归类。

视频页面则使用两列瀑布流卡片展示封面、时长、摘要以及作者信息。

为了改善重复进入个人主页时的等待时间,项目内部还加入了内存级缓存以及后台预取机制,在合适的情况下提前准备下一页内容和视频资源。

九、评论与内容互动

详情页提供完整的评论区域。

主要包括:

  • 一级评论;
  • 二级回复;
  • 评论输入;
  • 表情输入;
  • 回复;
  • 复制;
  • 图片预览。

评论中的图片数据会经过独立校验,避免把普通网页链接、搜索卡片或其他非图片内容错误地当成图片处理。

对于真正的图片附件,则直接使用原生图片组件展示,并可以进入统一的高清画廊。

十、编辑与发布

客户端提供独立的内容编辑页面。

目前支持:

  • 多图选择;
  • 图片预览;
  • 单张图片删除;
  • 表情输入;
  • 字数统计;
  • 定位信息;
  • 发布设备信息;
  • 内容编辑。

图片选择采用系统相册,并支持一次选择多张图片。

编辑页面的布局也进行了专门优化,例如把附加信息入口放在顶部,把定位和字数统计放在输入区域附近,把主要发送操作放到底部右侧。

十一、网络层设计

网络请求由统一的客户端进行管理。

主要职责包括:

  • 请求头统一处理;
  • 会话信息管理;
  • 身份状态检测;
  • 请求错误拦截;
  • 鉴权失效处理;
  • 必要时的有限重试;
  • 不同数据接口的独立封装。

一个比较重要的设计是防止鉴权失败导致无限重试。

当请求出现特定鉴权错误时,网络拦截器只允许有限次数的重新验证。如果再次失败,就直接把错误交给上层,而不会递归重试。

这样可以避免网络异常或者会话失效时出现请求风暴。

十二、本地数据与隐私设计

项目涉及账号会话和个性化配置,因此本地数据管理是一个需要特别注意的部分。

项目目前采用本地持久化保存必要的配置,并对可导出的数据设置明确白名单。

对于配置备份,只允许导出主题、字体、布局、分组排序、搜索历史、浏览历史等非敏感配置。

账号 Cookie、Access Token、WebDAV 密码等敏感凭据不会进入普通配置导出文件。

这意味着即使用户把普通配置备份文件交给其他设备使用,也不会因为备份文件本身而直接暴露完整账号会话。

十三、WebDAV 跨设备备份

除了本地存储之外,Review 还提供可选的 WebDAV 备份能力。

用户可以使用兼容标准 WebDAV 协议的服务,例如个人服务器、私有云或其他 WebDAV 存储。

主要用于保存:

  • 主题配置;
  • 字体与布局;
  • 分组设置;
  • 时间显示规则;
  • 图片和视频存储路径;
  • 搜索历史;
  • 浏览历史等。

备份采用 JSON 结构保存,并支持最新备份以及历史备份。

整个功能的设计目标并不是建立新的云服务,而是利用用户已有的 WebDAV 存储完成跨设备迁移。

十四、项目构建

当前项目主要面向 Android arm64-v8a

环境要求:

  • Flutter SDK >= 3.19.0
  • Dart SDK >= 3.3.0
  • JDK 17
  • Android Gradle Plugin 8.x

获取依赖:

1
flutter pub get

运行测试:

1
flutter test

构建 Release APK:

1
flutter build apk --release --target-platform android-arm64 --android-skip-build-dependency-validation

构建完成后可以得到对应架构的 Release 安装包。

十五、开源与项目定位

Review 目前以开源项目的形式发布。

项目的主要目的,是记录一次完整的 Flutter Android 客户端开发实践,同时探索现代 Android UI、信息流交互、媒体浏览、网络层设计以及本地数据管理等问题。

它并不是为了替代任何官方客户端,也不试图重新实现一个完整的平台生态。

更准确地说,它是一次围绕第三方客户端设计、Flutter 工程实践以及 Android 原生能力结合的实验。

如果你也对 Flutter、Material 3、Android 客户端开发或者信息流产品设计感兴趣,可以直接查看项目源码:

GitHub: https://github.com/Chengeeker/Review

结语

Review 从一开始就不是一个单纯的 UI Demo。

从信息流路由,到状态管理;从图片画廊,到长图手势;从 Material 3 动态主题,到 Android 原生媒体存储;从网络鉴权,到本地配置备份,这个项目实际上涵盖了一个完整移动客户端中相当多的工程问题。

对我来说,这个项目最大的价值并不是最终做出了多少功能,而是在开发过程中不断验证一个问题:

如果把一个成熟的信息流产品重新从客户端角度设计一遍,怎样才能让它变得更加简单、顺滑和可控?

这也是 Review 后续继续迭代的方向。

最后,感谢 https://github.com/Zelayan/share 这个开源项目,重现了一个经典的开源客户端,节省了我大量的开发时间,同时也感谢Share、See等前辈的付出,提供了功能设计的思路。