6.4 移动应用后端与 API 服务


6.4 移动应用后端与 API 服务

直接定义:移动应用后端要解决的,除了和普通 Web 一样的认证与数据,还多了三件移动特有的事——弱网下的离线、系统推送通知、和商店的登录合规。Supabase 的 SDK 原生覆盖 iOS/Android,这一节我们讲它怎么当移动后端,以及离线、推送怎么接。

下面 SVG 先给出移动端的整体架构,看清"本地队列—同步—推送"三层怎么摆:

6.4 移动应用后端与 API 服务

移动端 SDK 与登录

iOS 用 supabase-swift,Android 用 supabase-kotlin,调用形态和 Web 一致。登录同样拿到 JWT,查询走同一套 RLS。

// iOS (Swift) import Supabase let client = SupabaseClient(supabaseURL: URL, supabaseKey: anonKey) try await client.auth.signIn(email: "a@b.com", password: "secret") let todos = try await client.from("todos").select().execute().value as [[String: Any]]
// Android (Kotlin) val supabase = createSupabaseClient(supabaseUrl, anonKey) { install(GoTrue) ; install(Postgrest) } supabase.auth.signInWith(Email) { email = "a@b.com"; password = "secret" } val todos = supabase.from("todos").select().decodeList<Todo>()

注意:移动端持久化登录态由 SDK 处理,App 重启后自动恢复会话,不用自己存 token。

离线优先:先写本地再同步

移动网络不稳,好的体验是"操作先落本地、联网再同步"。Supabase 的实时和幂等写入能支撑最终一致。做法是本地队列存待同步操作,恢复网络后重放:

// 伪代码:离线队列重放(概念,非特定 SDK) async function flushQueue() { for (const op of localQueue) { await supabase.from(op.table).insert(op.row) // 幂等靠唯一约束 localQueue.remove(op) } }

关键在于服务端表要有幂等保障(如唯一约束),重放不会产生重复行。

-- 用唯一约束让重放安全 create table public.sync_items ( id uuid primary key default gen_random_uuid(), client_uuid uuid unique, -- 客户端生成的去重键 payload jsonb );

推送通知的桥接

Supabase 本身不发 APNs/FCM 推送,但可以用 Edge Function 在事件发生时调用推送服务(密钥存函数环境变量)。下面用触发器 + outbox + 函数做"新消息推通知":

-- outbox 记录待推送事件 create table public.push_outbox ( id bigint generated always as identity primary key, user_id uuid, title text, body text, sent boolean default false );
// Edge Function: 读 outbox 调 FCM(示意,密钥在服务端) Deno.serve(async () => { const admin = createClient(URL, SERVICE_ROLE) const { data: pending } = await admin .from('push_outbox').select('*').eq('sent', false).limit(100) for (const p of pending) { await fetch('https://fcm.googleapis.com/...', { /* 调推送 */ }) await admin.from('push_outbox').update({ sent: true }).eq('id', p.id) } return new Response('done') })

展开案例:健身 App 的离线打卡

背景:一个健身 App 用户在地铁里打卡,网络断断续续,不能因离线丢记录。

操作过程:

  1. 客户端本地 SQLite 存打卡记录,标记 synced=false
  2. 网络恢复时,把未同步记录批量 insert 到 Supabase 的 workouts 表,表带 client_uuid 唯一约束防重。
  3. 服务端 workouts 的 RLS 保证用户只能写自己的行。
  4. 打卡数变化通过 Realtime 推回 App 首页更新统计。
create table public.workouts ( id bigint generated always as identity primary key, user_id uuid references auth.users(id), client_uuid uuid unique, kind text, done_at timestamptz ); alter table public.workouts enable row level security; create policy "自己写自己" on public.workouts for all using (auth.uid() = user_id) with check (auth.uid() = user_id);

结果:地铁里断网照常打卡,恢复后无缝同步,重复提交被唯一约束挡掉,统计实时更新。

解读:移动后端的核心不是"多写接口",而是"离线不丢 + 同步幂等 + 权限在库"。Supabase 用 RLS + 唯一约束 + 实时把这三点都覆盖了,移动端只管本地队列。

变式:若推送量巨大,别用函数轮询 outbox,改由消息队列触发函数,函数只处理单条事件,扩展性更好。小体量用定时函数扫 outbox 足够。

本节要点回顾

  • iOS/Android SDK 调用形态与 Web 一致,登录态自动持久化。
  • 离线优先靠本地队列 + 唯一约束保证幂等重放。
  • 推送由 Edge Function 桥接 FCM/APNs,outbox 保证不丢。

⚠️ 移动端千万别把 service_role 打进 App 包。App 包可被反编译提取密钥,等于把数据库钥匙发给每个用户。推送等需要管理员权的逻辑,一律走服务端函数。

💡 我们建议离线同步一律加客户端生成的去重键(唯一约束),否则弱网下重试会产生重复业务记录。这是移动后端最容易翻车的点,比选哪个 SDK 更重要。

下一节看游戏后端:玩家档案、排行榜、实时对战,Supabase 能覆盖多少、哪部分要自己造。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U