ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Android ExpandableListActivity 学习笔记:TaoToken 统一 Key 接入与 settings.json 配置骨架

2026/9/29 8:10:40 拓冰建站 浏览量
Android ExpandableListActivity 学习笔记:TaoToken 统一 Key 接入与 settings.json 配置骨架 1. 从 ExpandableListActivity 说起老控件学习场景里的新需求Android 里的ExpandableListActivity是个挺有年代感的控件基类它继承自Activity内部帮你把ExpandableListView和ExpandableListAdapter的绑定逻辑都封装好了。你只要继承它、在onCreate里调一次setListAdapter一个可展开的二级列表就出来了。父级点一下展开子级再点一下响应事件做通讯录分组、设置项分类、商品类目这种场景特别顺手。但我在照着老教程敲示例的时候总会遇到一个很现实的问题学习笔记写到一半想顺手接个 AI 能力做点小实验比如把列表项内容丢给模型做摘要、或者让模型帮我生成测试数据结果卡在配置上。要么是每个工具各配一套 Key要么是环境变量、配置文件散落各处笔记还没写完配置先乱了。这时候如果有一个统一的 Key 和 API 通道把配置收敛到一个settings.json里学习节奏就不会被打断。这篇笔记就是围绕这个场景来的一边把ExpandableListActivity的三种典型绑定方式SimpleExpandableListAdapter、SimpleCursorTreeAdapter、BaseExpandableListAdapter过一遍一边把 TaoToken 的统一 Key 接入配置骨架搭好让你在写学习笔记的同时能跑通一次真实请求确认配置生效。适合正在补 Android 基础控件、又想顺手把 AI 工具链接入流程走通的开发者。2. TaoToken 前置准备统一 Key 与 API 通道TaoToken 在这里扮演的角色是一个统一的模型调用入口。你不用为每个模型或工具单独维护一套鉴权信息而是拿一个 Key通过统一的 API 地址去请求。对学习笔记这种场景来说好处很直接配置项少、迁移成本低、写进settings.json里一目了然。你需要先拿到自己的 API Key。入口在控制台的 API Keys 页面登录后创建一个即可。创建完记得复制保存页面上通常只完整显示一次。控制台入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 的基础地址是https://taotoken.net/api注意这个地址后面不加任何查询参数保持干净。请求时把 Key 放在Authorization头里格式是Bearer 你的Key。这套约定和主流 OpenAI 兼容接口一致所以你在 Android 侧用 OkHttp、Retrofit 或者干脆用 curl 验证写法都很熟悉。注意Key 属于敏感信息别硬编码进提交到 Git 的源码里。学习阶段可以放在本地settings.json并加入.gitignore正式项目建议走环境变量或密钥管理服务。3. 可复制的 settings.json 配置骨架下面这份settings.json是我在学习笔记里用的骨架把 TaoToken 的接入信息集中管理。你可以直接复制把apiKey换成自己的。{ taotoken: { baseUrl: https://taotoken.net/api, apiKey: sk-替换成你自己的Key, defaultModel: claude-3-5-sonnet, timeoutMs: 30000, headers: { Content-Type: application/json } }, android: { expandableList: { groupLayout: android.R.layout.simple_expandable_list_item_2, childLayout: android.R.layout.simple_expandable_list_item_2, groupFrom: [NAME, IS_EVEN], groupTo: [android.R.id.text1, android.R.id.text2] } } }几个字段说明一下。baseUrl固定用https://taotoken.net/api不要在后面拼/v1之类的路径具体端点由请求时补全。defaultModel填你打算默认调用的模型名学习阶段随便选一个能用的就行。timeoutMs给 30 秒模型请求比普通接口慢别设太短。headers里只放通用头鉴权头在代码里动态拼避免 Key 出现在静态配置的多个副本里。如果你在 Android 工程里读取这份配置可以放在assets/settings.json用AssetManager读进来解析。这样配置和代码分离改 Key 不用重新编译逻辑代码。fun loadSettings(context: Context): JSONObject { val text context.assets.open(settings.json) .bufferedReader().use { it.readText() } return JSONObject(text) }读出来之后taotoken.apiKey和taotoken.baseUrl就是后续请求要用的两个核心值。4. 最小验证跑通一次请求并确认配置生效配置搭好了得验证它真的能用。最直接的方式是先脱离 Android用命令行确认 Key 和地址没问题再回到工程里接。先看命令行验证。把下面的YOUR_KEY换成你的 Key直接执行curl -X POST https://taotoken.net/api/chat/completions \ -H Authorization: Bearer YOUR_KEY \ -H Content-Type: application/json \ -d { model: claude-3-5-sonnet, messages: [ {role: user, content: 用一句话说明 ExpandableListActivity 的作用} ] }如果返回里带有choices字段和模型输出内容说明 Key、地址、模型名三者都对上了。这一步过了再往 Android 里搬。Android 侧用 OkHttp 发同样的请求核心代码如下val client OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build() val settings loadSettings(context) val apiKey settings.getJSONObject(taotoken).getString(apiKey) val baseUrl settings.getJSONObject(taotoken).getString(baseUrl) val body JSONObject().apply { put(model, claude-3-5-sonnet) put(messages, JSONArray().put(JSONObject().apply { put(role, user) put(content, 用一句话说明 ExpandableListActivity 的作用) })) }.toString() val request Request.Builder() .url($baseUrl/chat/completions) .addHeader(Authorization, Bearer $apiKey) .addHeader(Content-Type, application/json) .post(body.toRequestBody(application/json.toMediaType())) .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { Log.e(TaoToken, 请求失败: ${e.message}) } override fun onResponse(call: Call, response: Response) { val result response.body?.string() Log.d(TaoToken, 返回: $result) } })跑起来后看 Logcat如果打印出模型返回的文本配置就生效了。这时候你可以把这段请求逻辑挂到ExpandableListActivity的某个子项点击事件上比如点开某个分组后把子项内容发给模型做处理学习笔记的示例就活了。5. 本篇常见错排查配置和请求过程中有几个坑我踩过列出来帮你省时间。第一个是 401 未授权。多半是 Key 拼错、复制时带了空格或者Authorization头里忘了Bearer前缀。检查一下头部的完整格式Bearer和 Key 之间是一个空格。第二个是 404 路径错误。常见原因是把baseUrl写成了https://taotoken.net/api/v1然后请求时又拼了/chat/completions变成/api/v1/chat/completions。按本文约定baseUrl保持https://taotoken.net/api端点直接拼/chat/completions。第三个是超时。模型请求比普通接口慢默认超时太短会直接失败。把连接和读取超时都设到 30 秒以上别用默认值。第四个是 Android 主线程网络异常。NetworkOnMainThreadException说明你把请求放在了主线程用enqueue异步或者切到子线程即可。第五个是settings.json读取失败。确认文件放在assets目录下且AssetManager的路径没有多余前缀。解析时用 try-catch 包一下打印原始文本方便定位。提示如果请求返回 200 但内容为空检查model字段是不是写了一个不存在的模型名。换一个文档里列出的模型再试。6. 后续怎么用从学习笔记到长期编码验证跑通之后这份配置骨架就能复用了。如果你只是偶尔在学习笔记里调一下模型用 API Keys 加接入文档的方式最轻量随用随配。文档地址在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content如果你想在模型对话里直接对比不同模型的输出效果可以走模型对话入口省去自己写请求的功夫https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content要是你打算把 AI 能力长期接进编码流程比如让 Agent 帮你补全ExpandableListAdapter的样板代码、生成测试数据那 Coding Plan 更合适配置一次就能持续用https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content回到ExpandableListActivity本身三种适配器各有适用场景。SimpleExpandableListAdapter适合静态的ListMap数据写示例最快SimpleCursorTreeAdapter适合数据来自数据库游标的场景父子查询分离BaseExpandableListAdapter最灵活视图完全自定义适合复杂布局。你可以把本文的请求逻辑分别挂到这三种适配器的点击回调里对比一下哪种更适合你的笔记结构。配置这件事一次搭好后面就只剩写业务逻辑了。