You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hilt结合SocketIO时如何获取最新accessToken及管理连接

使用Hilt实现Socket功能的问题及解决方案

现有代码实现

RepositoryModule

@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
    @Provides
    fun provideSocketRepository(socket: Socket): SocketRepository {
        return SocketRepository(socket)
    }
}

ServiceModule

@Module
@InstallIn(SingletonComponent::class)
object ServiceModule {
    @Provides
    fun provideSocket(): Socket {
        logd("socket: accessToken: ${Common.accessToken}")
        val options = IO.Options().apply {
            timeout = 30000
            reconnection = true
            reconnectionDelay = 1000
            reconnectionAttempts = 300
            transports = arrayOf(WebSocket.NAME)
            extraHeaders = mapOf(
                "Authorization" to listOf("Bearer ${Common.accessToken}"),
                "Content-Type" to listOf("application/json"),
                "identity" to listOf("app")
            )
        }
        return IO.socket(UrlType.BACK_OFFICE_SERVER.getUrl(), options)
    }
}

问题及解决方案

问题1:获取更新后的accessToken并更新Socket实例

当前Common.accessToken是全局变量,登录后更新无法同步到已注入的Socket实例,可按以下方式重构:

  1. 用Hilt注入的Token管理类替换全局变量
    定义单例Token管理类,统一处理Token的存储与更新:

    @Singleton
    class TokenManager {
        var accessToken: String? = null
            private set
    
        fun updateToken(newToken: String) {
            accessToken = newToken
        }
    }
    

    在Hilt模块中提供该实例:

    @Module
    @InstallIn(SingletonComponent::class)
    object TokenModule {
        @Provides
        fun provideTokenManager(): TokenManager = TokenManager()
    }
    
  2. 实现动态更新的SocketProvider
    不再直接提供Socket实例,而是通过SocketProvider管理Socket的创建与更新:

    @Singleton
    class SocketProvider @Inject constructor(
        private val tokenManager: TokenManager
    ) {
        private var currentSocket: Socket? = null
    
        fun getSocket(): Socket {
            val token = tokenManager.accessToken ?: throw IllegalStateException("Token未初始化")
            
            // 检查现有Socket的Token是否过期,过期则销毁重建
            currentSocket?.let { oldSocket ->
                val oldTokenHeader = oldSocket.options().extraHeaders["Authorization"].orEmpty()
                if (!oldTokenHeader.contains("Bearer $token")) {
                    oldSocket.disconnect()
                    currentSocket = null
                }
            }
    
            return currentSocket ?: run {
                val options = IO.Options().apply {
                    timeout = 30000
                    reconnection = true
                    reconnectionDelay = 1000
                    reconnectionAttempts = 300
                    transports = arrayOf(WebSocket.NAME)
                    extraHeaders = mapOf(
                        "Authorization" to listOf("Bearer $token"),
                        "Content-Type" to listOf("application/json"),
                        "identity" to listOf("app")
                    )
                }
                IO.socket(UrlType.BACK_OFFICE_SERVER.getUrl(), options).also {
                    currentSocket = it
                }
            }
        }
    
        // 登录更新Token后调用,触发Socket重建
        fun onTokenUpdated() {
            currentSocket?.disconnect()
            currentSocket = null
        }
    }
    
  3. 修改Repository依赖SocketProvider

    @Module
    @InstallIn(SingletonComponent::class)
    object RepositoryModule {
        @Provides
        fun provideSocketRepository(socketProvider: SocketProvider): SocketRepository {
            return SocketRepository(socketProvider)
        }
    }
    

    在SocketRepository中,每次使用Socket时通过socketProvider.getSocket()获取最新实例。


问题2:断开后重新连接的可行性

直接调用socket.disconnect()(不置为null)后再调用socket.connect()是可行的,但需注意:

  • Socket.IO实例本身支持多次连接/断开操作,未销毁的实例调用connect()会重新发起连接请求。
  • 但这种方式不会自动更新Socket的header配置,如果Token已更新,旧实例的请求头仍会使用旧Token,因此建议结合上述SocketProvider方案,在Token更新时重建Socket实例。
  • 需监听Socket连接状态,避免重复调用connect()引发异常。

内容的提问来源于stack exchange,提问作者c-an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:42:55