Xposed 模块开发踩坑之:不要使用 Retrofit
您现在是在。
背景
如题,我的结论是在 xposed 模块里面网络请求不要使用 retrofit。或者其实是可以用的,但是至少很容易出问题,所以还是避免的好,直接用 okhttp 和 ktor 都行。
关于这个问题,我已经搞了好几天了。
一开始我用 retrofit 来实现 xposed 模块内网络请求,遇到 call adapter 错误
我的修复过程:
- 我几乎看过所有 csdn 和 stateflow 上的讨论,包括导入特定的 call adapter,结果都没用,但是在主应用进行网络请求根本不会有这个问题
- 我以为是因为目标 hook 应用里面也有 retrofit,而且是 api 不兼容的版本才导致这个问题,所以我又用
shadowJar来改 retrofit 的包名,改完编译完还是不行 - 现在完全移除 retrofit2 依赖,用纯 okhttp 实现,终于解决!
总得来说,在 Xposed 这种特殊的运行环境中,问题往往比想象的要更深一些。
gemini-2.5-pro 的看法:
这通常不是简单的类名冲突,而是和 ClassLoader(类加载器)以及反射(Reflection)机制的复杂交互有关。
-
Retrofit 的工作原理:Retrofit 在背后做了大量的反射工作来解析您定义的
IChatService接口、方法注解 (@POST) 和返回值类型(比如suspend函数或者Flow<>)。它需要根据这些信息动态地创建一个实现类,并找到合适的CallAdapter来处理异步调用。 -
Xposed 的环境:在 Xposed 模块中,您的代码是被注入到目标应用的进程里运行的。这意味着您的代码和目标应用共享一个非常复杂的运行时环境和 ClassLoader。
-
问题的根源:当您的 Retrofit 实例试图进行反射操作时,很可能受到了目标应用已加载的类(包括它自己的旧版 Retrofit/OkHttp,甚至是其他库)的干扰。这种干扰会导致 Retrofit 的
CallAdapter.Factory无法正确识别或创建处理suspend函数所需适配器,从而抛出错误。shadowJar能解决类名冲突,但解决不了这种深层的 ClassLoader 和反射逻辑的混乱。
而当您换用纯 OkHttp 后,您等于完全绕过了 Retrofit 整个复杂的“接口定义 -> 反射 -> 动态代理 -> 创建请求”的流程。
您现在是在直接、显式地构建一个 Request 对象,然后把它交给 OkHttpClient 执行。这个过程清晰明了,几乎不涉及复杂的反射,因此在任何环境下都非常稳定、可靠。
结论
在复杂环境下开发,不管是自己进行反射操作,还是使用大量使用反射的第三方库,都要谨慎,不然遇到类似这样的问题真的太搞了
更多推荐
所有评论(0)