{"id":21462258,"url":"https://github.com/espoirx/bumblebee","last_synced_at":"2025-07-15T03:30:49.545Z","repository":{"id":224501839,"uuid":"763421131","full_name":"EspoirX/Bumblebee","owner":"EspoirX","description":"基于 有限状态机 和 Flow 的 WebSocket 封装，Socket 部分 用 OkHttp 实现。 1. 支持 Flow 2. Socket 的状态由状态机管理，自动处理重连等逻辑 3. Socket 部分默认由 OKHttp 实现  4. 使用简单，跟你使用 Retrofit 差不多","archived":false,"fork":false,"pushed_at":"2024-05-30T09:43:33.000Z","size":164,"stargazers_count":44,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-30T17:47:54.665Z","etag":null,"topics":["machine","okhttp-websocket","retrofit","retrofit2","socket","state-machine","websocket"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EspoirX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-26T09:06:38.000Z","updated_at":"2024-10-18T07:41:33.000Z","dependencies_parsed_at":"2024-10-30T17:41:08.872Z","dependency_job_id":null,"html_url":"https://github.com/EspoirX/Bumblebee","commit_stats":null,"previous_names":["espoirx/bumblebee"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EspoirX%2FBumblebee","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EspoirX%2FBumblebee/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EspoirX%2FBumblebee/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EspoirX%2FBumblebee/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EspoirX","download_url":"https://codeload.github.com/EspoirX/Bumblebee/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226012288,"owners_count":17559651,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["machine","okhttp-websocket","retrofit","retrofit2","socket","state-machine","websocket"],"created_at":"2024-11-23T07:13:20.379Z","updated_at":"2024-11-23T07:13:20.962Z","avatar_url":"https://github.com/EspoirX.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bumblebee\n## 基于 有限状态机 和 Flow 的 WebSocket 封装，Socket 部分 用 OkHttp 实现\n\n# 特点：\n1. 支持 Flow\n2. Socket 的状态由状态机管理，自动处理重连等逻辑\n3. Socket 部分默认由 OKHttp 实现\n4. 使用简单，跟你使用 Retrofit 差不多\n\n## 引入\n```groovy\ndependencies {\n  implementation 'com.github.EspoirX:Bumblebee:TAG'\n}\n```\n[![](https://jitpack.io/v/EspoirX/Bumblebee.svg)](https://jitpack.io/#EspoirX/Bumblebee)\n\n## 使用\n### 1. 首先创建一个服务接口\n```kotlin\n\ninterface SocketService {\n    //......\n}\n```\n\n### 2. 创建服务实例\n```kotlin\nobject SocketManager {\n    private val mainScope = MainScope()\n    private val url = \"wss://xxx.xxx.xxx\"\n\n    private var socketService: SocketService? = null\n\n    fun provideSocketService() {\n        if (socketService != null) return\n        val client = OkHttpClient.Builder()\n            .retryOnConnectionFailure(true)\n            .pingInterval(5000, TimeUnit.MILLISECONDS)\n            .build()\n        val header = arrayMapOf\u003cString, String\u003e()\n        //...\n        val socket = Bumblebee.Builder()\n            .webSocketFactory(client.newWebSocketFactory(url, header))\n            .log(object : BumblebeeLog {\n                override fun log(tag: String, msg: String) {\n                    Log.i(TAG, msg)\n                }\n            }).build()\n\n        socketService = socket.create()\n    }\n}\n```\n通过 Bumblebee.Builder 构建实例，可配置 OkHttpClient，可以添加 Header 之类的参数。  \n\n可以配置 BumblebeeLog 接口，自己实现 Log 打印，不配置的话默认使用 android.util.Log 打印。\n\n然后通过 create 方法即可创建实例。\n\n**在创建实例成功后，会自动打开连接。**\n\n### 3. 连接，断开链接，发送，接收\nBumblebee 有四个注解，分别是：  \n**@ConnectionService**   //主动打开 socket 链接  \n**@ConnectionShutdown**  //主动断开 socket 链接  \n**@Send**                //发送消息  \n**@Receive**             //接收消息\n\n使用也简单，在服务接口中添加对应的方法即可\n```kotlin\ninterface SocketService {\n\n    @ConnectionService\n    fun connectionService(): Boolean\n\n    @ConnectionShutdown\n    fun connectionShutdown(): Boolean\n\n    @Send\n    fun sendMessage(message: String): Boolean\n\n    @Receive\n    fun observeText(): Flow\u003cMessage\u003e\n\n    @Receive\n    fun observeState(): Flow\u003cMachineState\u003e\n    \n    //......\n}\n```\n- 被 @ConnectionService 修饰的方法，不能有参数，需要有返回值 Boolean，调用即可主动打开 Socket 链接，前提是当前链接是关闭状态，不然不会重复打开。使用例子：\n```kotlin\n   socketService?.connectionService()\n```\n\n- 被 @ConnectionShutdown 修饰的方法，不能有参数，需要有返回值 Boolean，调用即可主动断开 Socket 链接。使用例子：\n```kotlin\n   socketService?.connectionShutdown()\n```\n\n- 被 @Send 修饰的方法，需要有参数，String 类型，需要有返回值 Boolean，调用即可主动给 Socket 服务端发送一条消息。\n通常传一个 json 字符串。使用也是一样：\n```kotlin\n    socketService?.sendMessage(\"{...}\")\n```\n\n- 被 @Receive 修饰的方法，代表接收一个消息，不能有参数，需要返回 Flow 类型，下面细说。\n\nBumblebee 将消息包装成了 Message ，里面包含 Text 和 Bytes 类型\n\n```kotlin\nsealed class Message {\n    data class Text(val value: String) : Message()\n    class Bytes(val value: ByteArray) : Message() {\n        operator fun component1(): ByteArray = value\n    }\n}\n```\n\n当我们需要常规接收服务端推送过来的消息时，Flow 类型需要为 Message（如上例子的代码所示）。那么接收时可以根据自己需要看是\n过滤 Text 类型还是 Bytes 类型。（通常都是 Text）\n```kotlin\n    fun observeText() = socketService?.observeText()\n        ?.filter { it is Message.Text }\n        ?.map { (it as Message.Text).value }\n    //......\n    SocketManager.observeText()?.map { message -\u003e\n       //... \n    }?.catch { it.printStackTrace() }?.launchIn(mainScope)\n```\n如此，就完成了消息接收。\n\n除了 Message ，如果你想要接收 Socket 的状态信息，那么 Flow 类型可以写成 MachineState。MachineState \n是状态机的状态，也是代表着当前的链接状态：\n```kotlin\nsealed class MachineState {\n    //重试状态\n    data class WaitingToRetry internal constructor(val retryCount: Int, val retryInMillis: Long, ) : MachineState()\n    //链接中状态\n    data class Connecting internal constructor(internal val session: Session, val retryCount: Int, ) : MachineState()\n    //已链接状态\n    data class Connected internal constructor(internal val session: Session) : MachineState()\n    //断开中状态\n    object Disconnecting : MachineState()\n    //已断开状态\n    object Disconnected : MachineState()\n}\n```\n比如我想监听当前是否已经链接成功可以这样写：\n```kotlin\n    fun observeState() = socketService?.observeState()\n    //......\n    var isConnectOpen : Boolean = false\n\n    SocketManager.observeState()?.map {\n        isConnectOpen = it is MachineState.Connected\n    }?.catch { it.printStackTrace() }?.launchIn(mainScope)\n```\n\n除了 MachineState，你还可以通过 @Receive 监听 socket 当前回调了哪个方法（对应 OKHttp 的 WebSocketListener），只需要\n将 Flow 类型改成 WebSocket.Event 即可：\n```kotlin\n    @Receive\n    fun observeEvent(): Flow\u003cWebSocket.Event\u003e\n```\nWebSocket.Event 的代码就不贴了，都是对应相关的回调，自己点下看看就可以，想监听哪个就过滤哪个就行。\n\n### 4. 重试逻辑\n当 socket 关闭或者非主动关闭时，会通过状态机自动进入重试逻辑。重试频率间隔通过 BackoffStrategy 接口控制：\n```kotlin\ninterface BackoffStrategy {\n    fun backoffDurationMillisAt(retryCount: Int): Long\n}\n```\n返回毫秒。  \n\n**返回 -1 代表取消重连，转断开**\n\n默认的重试逻辑是 5 秒重试一次，6 次后休息 10 秒再重复：\n```kotlin\nclass LinearBackoffStrategy(private val durationMillis: Long) : BackoffStrategy {\n    override fun backoffDurationMillisAt(retryCount: Int): Long {\n        if (retryCount \u003e 0 \u0026\u0026 retryCount % 6 == 0) {\n            return 10000\n        }\n        return durationMillis\n    }\n}\n```\n\n如果你要自定义，则可以在初始化的时候通过 backoffStrategy 方法传入你的实现即可：\n```kotlin\n  val socket = Bumblebee.Builder()\n        .webSocketFactory(client.newWebSocketFactory(url, header))\n        .backoffStrategy( ... )\n        .build()\n```\n\n就这些啦。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fespoirx%2Fbumblebee","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fespoirx%2Fbumblebee","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fespoirx%2Fbumblebee/lists"}