跳至正文

宿主要接的那几件事

SDK 大部分能力是你主动调用它。但有几件事反过来:核心拿不到,只能由宿主 (你的 App)告诉它。这几个方法都标记为 stable,此前官网没有文档—— 不知道它们存在,接入就会缺一块,而缺的这块通常表现为「偶发的连不上 / 启动慢 / 消息里名字头像是空的」,很难往这个方向排查。

网络切换:client.connection.notifyNetworkChange

核心不监听系统网络事件——那是平台 API,各端不同,塞进核心就得写四遍。 宿主拿到网络变化时喂给它:

// iOS: NWPathMonitor / Android: ConnectivityManager / Web: navigator.onLine
client.connection.notifyNetworkChange({
  available: true,
  interface: 'wifi',       // 'wifi' | 'cellular' | ...
  expensive: false,
  metered: false,
  reason: 'path satisfied', // 仅用于诊断日志
})

不喂的后果是:断网后核心只能等 TCP/心跳超时才察觉,重连比实际可能的时机晚 几十秒。喂了它才能在网络刚恢复时立刻重连。

字段都是可选的:available 省略视为可用;不确定的项不必硬填。

启动首屏:client.sync.bootstrapStartupHome

冷启动时一次性把「首屏要显示的会话」拉齐,而不是等各个模块各自同步:

const res = await client.sync.bootstrapStartupHome({
  conversationLimit: 20,
  startBackgroundConvergence: true,   // 首屏拿到后,后台继续补齐其余
  backfillVisibleHistories: true,     // 顺带预取可见会话的少量历史
  historyBackfillLimit: 20,
  historyBackfillMaxPagesPerConversation: 1,
  historyBackfillMaxConversations: 8,
})

if (res.degradedReason) {
  // 降级了(例如网络差、冷同步未完成):首屏可能不全,
  // 此时该显示本地缓存而不是空列表
  console.warn('startup degraded:', res.degradedReason)
}

返回里 coldSyncPerformedbackgroundConvergenceStarted 告诉你这次是冷同步 还是走了缓存,便于埋点对比启动耗时。

身份显示:client.user.upsertUserProfiles

开源栈不含账号体系,所以核心不知道用户叫什么、头像是什么。消息里的 昵称与头像由你喂进来,核心负责缓存与批量 join:

await client.user.upsertUserProfiles({
  profiles: [
    { userId: 'u_1001', nickname: '张三', avatarUrl: 'https://.../a.png' },
    { userId: 'u_1002', nickname: '李四', avatarUrl: 'https://.../b.png' },
  ],
})

不喂的话消息能收发、顺序也对,但列表里是一片空白的名字与头像—— 这是「开源部分不含账号体系」在 UI 上最直接的体现。

自签 token:client.generateCoreToken

评估阶段用它签一个能连上网关的 token,不需要任何用户体系:

const { token } = await client.generateCoreToken({
  userId: 'alice',
  secret: gatewaySecret,    // 与网关 token_secret 相同
  issuer: 'flare-im-core',  // 与网关 token_issuer 相同
  ttlSecs: 3600,
})

secret 或 issuer 与网关不一致时,握手会被拒——而客户端看到的往往只是 「连接超时」。这是接入阶段最常见的一个坑,值得先核对这两项。

生产环境不要用它:密钥出现在客户端等于人人可签任意身份。 生产应由你的服务端签发,或走 Hook 校验。

诊断:client.diagnostics

排障时用,不参与业务:

方法用途
getRuntimeHealth当前连接状态、会话代数、被丢弃的事件计数
getDataRoot本地存储位置,排查「数据去哪了」
getFfiContractVersion原生桥接的契约版本,排查版本错配

getRuntimeHealth 里的 rawSubscriberDroppedTotal 值得关注:它不为 0 说明 事件队列曾满而丢过事件,通常意味着上层消费太慢。

生命周期:uninit / hardReset

  • uninit:释放 SDK 占用的资源。切换账号或退出登录时调用。
  • hardReset:清空本地状态重来。仅用于「本地数据疑似损坏」的兜底, 它会丢弃本地缓存,不要当成常规的登出。

心跳(一般不用改)

setHeartbeatNatTimeoutheartbeatEffectiveInterval 用于适配特定网络环境下 NAT 的空闲回收时间。默认值适用于绝大多数场景,只有在「链路总是被中间设备掐断」 时才需要按实测的 NAT 空闲超时调整。

两个变体方法

它们与上面的能力同族,按需要选用:

  • client.events.subscribeEventsBatch:一次订阅多类事件,等价于多次 subscribeEvents,用于减少跨 FFI 的调用次数。
  • client.sync.backfillConversationHistory:只回填单个会话的历史, 用于「进入某个老会话时才补」;bootstrapStartupHomebackfillVisibleHistories 是它的批量版。

相关