Android中Kotlin类如何传递Context至ApiClient添加设备UUID请求头
我来给你梳理下可行的解决方案,核心是让你的单例ApiClient能拿到安全的Context,同时避免内存泄漏问题:
第一步:修改ApiClient的构造与单例逻辑
首先调整ApiClient的结构,让它能接收Context并保存Application Context(这是关键,避免持有Activity/Fragment Context导致内存泄漏),同时在拦截器中调用你的UUID扩展方法:
class ApiClient private constructor(private val appContext: Context) { private val apiServices: ApiServices init { // Gson配置保持不变 val gson = GsonBuilder() .setLenient() .create() // 日志拦截器配置保持不变 val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE // OkHttpClient构建器:添加UUID请求头 val clientBuilder = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .addInterceptor { chain -> val originalRequest = chain.request() // 调用扩展方法获取设备UUID val deviceUuid = appContext.getDeviceUUID() // 构建新请求并添加uuid头 val newRequest = originalRequest.newBuilder() .addHeader("uuid", deviceUuid) .build() chain.proceed(newRequest) } .readTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS) .writeTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS) .connectTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS) .retryOnConnectionFailure(true) val client = clientBuilder.build() // Retrofit配置保持不变 val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())) .build() apiServices = retrofit.create(ApiServices::class.java) } companion object { @Volatile private var apiClient: ApiClient? = null // 提供带Context的单例获取方法,确保线程安全 fun getInstance(context: Context): ApiClient { return apiClient ?: synchronized(this) { apiClient ?: ApiClient(context.applicationContext).also { apiClient = it } } } } // 暴露ApiServices供外部调用 fun getApiServices(): ApiServices = apiServices }
第二步:全局初始化ApiClient
建议在你的Application类的onCreate方法中完成初始化,这样整个应用生命周期内只创建一次实例,且确保拿到的是全局安全的Application Context:
class MyApp : Application() { override fun onCreate() { super.onCreate() // 初始化ApiClient,传入Application Context ApiClient.getInstance(this) } }
别忘了在AndroidManifest.xml中配置你的Application类:
<application android:name=".MyApp" ...> ... </application>
第三步:使用ApiClient
之后在需要调用接口的地方,直接获取实例即可:
val apiServices = ApiClient.getInstance(applicationContext).getApiServices() // 调用接口方法示例 apiServices.yourApiMethod().subscribe(...)
关键注意点
- 必须用
applicationContext:如果传入Activity/Fragment的Context,当组件销毁时,单例ApiClient仍持有引用会导致内存泄漏,Application Context的生命周期与应用一致,是安全选择。 - 双重检查锁机制:
@Volatile+synchronized确保多线程环境下不会创建多个ApiClient实例。
这样修改后,你的所有请求都会自动带上设备UUID请求头,同时完美解决了Context传入的问题。
内容的提问来源于stack exchange,提问作者KokoBand
相关产品推荐
相关产品推荐

