Dioxus 做移动端:能跑,但离上架还有多远

前言

前面几篇,我们一直在 Web 视角里看 Dioxus:

  • rsx! 怎么写
  • Signals 怎么管状态
  • 组件怎么拆
  • 路由怎么组织
  • 桌面端为什么也是 WebView,但和 Tauri 写起来不是一个感觉

到了移动端,话题就没法只停留在"语法顺不顺手"了。

因为桌面应用哪怕有点毛边,很多时候还能靠"内部工具""先交付再打磨"撑过去。手机不一样。大家一想到 Android 和 iOS,马上就会问这些更现实的问题:

  • 滑动手感怎么样
  • 长列表会不会掉帧
  • 相机、推送、蓝牙怎么接
  • 签名和上架麻不麻烦

所以这篇不聊 "Hello World 能不能亮起来"。那个问题太初级了。真正该问的是:Dioxus Mobile 现在到底能做什么,它又在哪些地方明显还不够。

1. 先把定位说清楚:它不是原生控件路线

如果只记一句话,我建议记这句:

Dioxus Mobile 能做移动应用,但它默认不是原生控件方案,本质上还是移动端 WebView 方案。

按 Dioxus 0.7 官方移动文档现在的表述,移动端支持已经是正式方向,渲染主要有两条路:

  • 平台 WebView
  • 实验性的 WGPU 渲染器

这件事决定了后面几乎所有判断。

换句话说,Dioxus Mobile 不是:

  • Flutter 这种自己管渲染管线的路子
  • React Native 这种强调原生控件映射的路子
  • SwiftUI / Jetpack Compose 这种平台原生 UI 框架

它更接近这样一套结构:

  • 外面是 Android Activity 或 iOS App 容器
  • 中间是平台运行时
  • 里面显示出来的界面,核心还是 HTML/CSS 那一套结果
  • 只是你写它时,用的不是 JS,而是 Rust 的 rsx!

所以如果有人问我"Dioxus Mobile 算不算能做移动端",我的回答会比较克制:

能做,但更像 Rust 版跨平台 WebView App。你别把它脑补成"Rust 版原生移动 UI 框架",这两个预期差得很远。

2. 它怎么跑起来

这个问题拿代码看最省事。

2.1 你写的还是那套熟悉的 Rust 组件

比如下面这段代码,前几篇跟下来的同学应该已经很熟了:

rust 复制代码
use dioxus::prelude::*;

fn main() {
    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    let mut keyword = use_signal(|| String::from("Dioxus Mobile"));
    let mut clicks = use_signal(|| 0);

    rsx! {
        div { class: "page",
            h1 { "一套 Rust 组件切到移动端" }
            input {
                value: "{keyword}",
                oninput: move |evt| keyword.set(evt.value()),
                placeholder: "输入点什么"
            }
            button {
                onclick: move |_| clicks += 1,
                "点了 {clicks} 次"
            }
        }
    }
}

这里有个很关键的事实:你没写 Android XML,也没写 SwiftUI / UIKit。

你写的还是:

  • Rust 组件
  • rsx! 描述 UI
  • Signals 管状态
  • Rust 闭包处理事件

这也是 Dioxus 最有吸引力的地方。它不是让你为 Android 重写一遍、再为 iOS 重写一遍,而是尽量让你守住一套组件和一套状态逻辑。

2.2 只是运行目标换成了移动端容器

切到移动端之后,Dioxus 不会把这些组件"翻译"成原生按钮和原生输入框。它做的事更接近于:

  • Android 侧把应用挂进 Android 容器
  • iOS 侧把应用挂进 iOS 容器
  • 最后界面仍由 WebView 渲染出来

这就是为什么你在 Web 端已经写好的东西,往往可以直接带过来:

  • 页面结构
  • CSS 样式
  • 组件拆分
  • 路由组织
  • 大部分状态逻辑

这部分确实很香。尤其是小团队,真的会少很多重复劳动。

2.3 原生能力可以接,但不是白送的

很多人一看到 WebView,就默认它只能做表单和展示页。这个结论也有点过了。

Dioxus 官方文档给的态度很明确:如果框架层没包好某个能力,你可以自己往平台 API 下钻。典型方式大概是这样:

  • Web 用 web-sys
  • Android 用 jni / jni-sys
  • iOS 用 objc2

比如你想按平台分别走桥接逻辑,可以这么写:

rust 复制代码
fn call_native_feature() {
    #[cfg(target_os = "android")]
    {
        // 这里可以通过 jni / jni-sys 调 Android 原生能力
    }

    #[cfg(target_os = "ios")]
    {
        // 这里可以通过 objc2 调 iOS 原生能力
    }
}

所以它不是完全封闭的。

但这里也有个很现实的代价:一旦你开始频繁接原生层,"一套 Rust 代码通吃全部"的轻松感就会明显下降。上层还是统一的,底下已经开始分叉了。

3. Android 和 iOS 的开发链路,比 Web 和桌面重得多

上一篇讲桌面端时,我说过 dx serve --platform desktop 的开发体验已经挺顺了。移动端没那么轻。

3.1 Android:先把工具链扛起来

按 Dioxus 0.7 官方移动文档,Android 侧至少要补这些 Rust 目标:

bash 复制代码
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

除此之外,还得准备:

  • Android Studio
  • Android SDK
  • Android SDK Command-line Tools
  • Android NDK
  • CMake

环境变量也要配:

  • JAVA_HOME
  • ANDROID_HOME
  • NDK_HOME
  • PATH

说白了,移动端的第一道门槛不是 Dioxus,而是 Android 工具链本来就不轻。你要是没碰过 Android 开发,光把环境配到能稳定编译,就已经够喝一壶了。

3.2 iOS:Xcode 这关也绕不过去

iOS 这边同样如此。

官方文档给出的基础目标安装是:

bash 复制代码
rustup target add aarch64-apple-ios aarch64-apple-ios-sim

然后你还得有:

  • Xcode
  • iOS SDK
  • Xcode Command Line Tools
  • iOS Simulator

做过 Apple 平台开发的人都知道,能编过只是开始。后面还有签名、调试、归档、提审,这些才是折磨人的部分。

3.3 命令入口这件小事,反而很说明问题

这里我专门提一句,免得被旧资料带偏。

很多文章、示例或者大家的旧记忆里,会写:

bash 复制代码
dx serve --platform android

这个命令并不是错的,很多本地 CLI 版本也确实还能这么用。

但按我在 2026 年 6 月 23 日 核对到的 Dioxus 0.7 官方移动文档,推荐流程更接近:

  1. 先启动 Android 模拟器或 iOS 模拟器
  2. 再在项目目录里运行:
bash 复制代码
dx serve

所以最稳的做法是:先看你本地 dx --help,再对照当前官方文档。

这看起来只是参数形式的小变化,其实很能说明阶段问题。移动端这条链路还在快速收敛,说明它确实在进步,但也说明开发体验还没完全定型。

4. 它更适合做什么 App

只问"能不能做"没太大意义。真正影响选型的是"适不适合做我这个东西"。

如果让我现在给判断,我会把 Dioxus Mobile 更偏向下面几类项目。

4.1 业务型、表单型、信息型 App

比如:

  • 企业内部审批 App
  • CRM / ERP 的移动入口
  • 业务录入工具
  • 数据查看面板
  • 订单中心、会员中心、消息中心这类页面

这类应用有个共同点:页面逻辑多,表单多,状态多,但最吃重的不是炫技动画,而是业务流转本身。

这刚好落在 Dioxus 相对舒服的区间里。因为你能复用现成的页面结构、Rust 业务逻辑、路由组织,还有一部分 CSS 体系。

4.2 先把多端版本跑起来的 MVP

还有一种场景也很适合:你现在不是要冲顶级移动体验,而是先把业务验证掉。

比如你想尽快把这些先跑通:

  • 账户体系
  • 列表和详情
  • 表单流程
  • Web、桌面、移动尽量共用一套逻辑

那 Dioxus 的吸引力就很直接了。它给你的不是某一端做到极致,而是让整体工程复杂度别一下子炸开。

小团队会特别能体会这一点。真正把项目拖死的,很多时候不是功能写不出来,而是仓库越开越多:前端一套、Android 一套、iOS 一套、后端一套,最后同步一个版本都头大。

4.3 团队 Rust 强,前端力量一般

这也是 Dioxus 很明确的一类受众。

如果你的团队:

  • Rust 能力不错
  • 前端人力一般
  • 又不想为了 App 单独引一整套 JS 工程

那 Dioxus Mobile 的思路是说得通的。因为你维护的是一个 Cargo 项目、一套组件模型、一套类型系统,而不是再养一个 React Native、Flutter 或原生移动仓库。

5. 真正难的,不是"跑起来",是"像不像一个像样的移动 App"

这部分我觉得才是重点。

5.1 触控体验不会自动变成原生味

官方移动文档说得很直接:当前并不支持原生 Android 动画和原生控件部件,主要依赖 CSS 动画和样式。

翻成人话就是:它能动,但那个手感不会天然等于原生移动 UI。

比如这些地方,最容易露馅:

  • 惯性滚动细节
  • 复杂手势反馈
  • 下拉刷新手感
  • 长列表复用体验
  • 系统级转场一致性

这些不是"页面能显示出来"就自动解决的。

如果你的产品特别在意那种原生味,比如 iOS 上滑动时那种跟手程度、列表滚起来的质感、手势和系统转场的契合感,那 Dioxus Mobile 至少在今天还不是个轻松选项。

5.2 性能边界还是会回到 WebView

上一篇桌面篇里我就提过,Dioxus 的很多性能讨论,最后都绕不开 WebView 这块地基。移动端只会更敏感。

因为手机面对的是:

  • 更紧的内存约束
  • 更明显的发热和功耗问题
  • 更容易暴露掉帧的滚动场景

所以如果你的页面主要是表单、详情、普通列表,配一点中轻量动画,通常问题不大。

但如果你做的是:

  • 大量复杂手势
  • 重动画交互
  • 高频图形更新
  • 对滚动性能特别挑剔的页面

那就别只盯着"能不能跑起来",而要盯着另一件更实际的事:它能不能长期稳定地跑得像个成熟 App。

5.3 原生能力一多,跨平台收益会被吃掉

理论上,你当然可以靠 jniobjc2 去接原生能力。

问题在于,一旦你的 App 很快要接这些东西:

  • 推送
  • 相机
  • 蓝牙
  • 文件系统
  • 后台任务
  • 分享面板
  • 生物识别
  • 深链接

项目形态就会开始变化。

现实通常会变成:

  • Android 一套桥接
  • iOS 一套桥接
  • Dioxus 上层再包自己的统一接口

你依旧在写 Rust,这没错。但这时候项目复杂度已经不是"轻松共享一切"的那种感觉了。Dioxus 的优势,更多体现在 UI 结构、业务状态和基础交互的复用;它并不等于"所有移动能力都自动跨平台"。

5.4 能出包,不等于能安心上架

很多框架介绍自己时,都容易把"能生成 APK / IPA"说得像"已经具备产品交付能力"。

这两件事差得很远。

移动端真正磨人的地方是:

  • 签名
  • 权限声明
  • 崩溃排查
  • 包体控制
  • 审核规范
  • 原生 SDK 兼容
  • 不同系统版本的行为差异

所以如果让我概括 Dioxus Mobile 现在的状态,我会这么说:

开发方向已经打通,工程闭环也在变完整,但离"拿来就能放心上架"的成熟感,还有一段距离。

6. 如果现在就选,它更适合谁

我给一个很直接的判断。

6.1 适合考虑 Dioxus Mobile 的场景

  • 你本来就打算用 Rust 做主栈
  • 你需要 Web、桌面、移动尽量复用代码
  • 你做的是内部系统、业务工具、MVP 或中轻量应用
  • 你接受必要时自己下钻到 JNI / Objective-C
  • 你更在意工程统一,而不是极致原生体验

6.2 暂时别急着上的场景

  • 你要做强原生质感的消费级 App
  • 你很依赖复杂手势、长列表和高频动画
  • 你需要成熟的移动原生插件生态
  • 你希望团队里的移动开发同学拿来就用,而不是一起啃 Rust 加平台桥接
  • 你上线目标非常依赖应用商店稳定交付和长期维护

一句话说完:Dioxus Mobile 更像跨平台 Rust 工程方案,不是移动端体验银弹。

7. 总结

Dioxus Mobile 当然不是不能做移动端。恰恰相反,它已经把最关键的路铺出来了:

  • Rust 写 UI
  • Rust 写状态
  • Android 和 iOS 都能作为正式目标
  • 需要时也能往 JNI、objc2 这些原生能力下钻

但你也别因为它"已经能跑",就顺手把它想成 Flutter、React Native 或成熟原生方案的平替。现在更准确的说法应该是:

它已经值得 Rust 团队认真评估,但它当前最大的价值仍然是代码统一和工程简化,不是移动体验上的全面领先。

如果你做的是业务型 App、内部工具或者 MVP,我觉得它很值得试。真要做强体验、强原生、重交互产品,那就别只看"跨平台"这三个字,先把触控、性能、原生能力和上架链路想清楚。

如果你已经试过 Dioxus Mobile,也欢迎聊聊你卡在哪一步:工具链、性能,还是原生能力接入。