Android Retrofit2使用SharedPreferences中Bearer Token授权遇空指针问题咨询
问题分析与解决方案
核心错误原因
你把RetrofitInstance定义为继承Application的object单例,这完全不符合Android组件的初始化逻辑:
- Android的
Application子类必须在AndroidManifest.xml中注册,且由系统在应用启动时自动初始化 object是Kotlin的饿汉式单例,其实例化时机不受Android系统控制,导致applicationContext还未初始化就被调用,触发空指针异常
修正后的实现方案
步骤1:创建全局Application类
先定义一个自定义的Application子类,用来提供全局可用的Context:
class MyApp : Application() { companion object { lateinit var instance: MyApp private set } override fun onCreate() { super.onCreate() instance = this } }
别忘了在AndroidManifest.xml的application标签中注册这个类:
<application android:name=".MyApp" <!-- 其他属性保持不变 --> >
步骤2:重构Retrofit单例
将RetrofitInstance改成普通的object,通过全局Application实例获取Context来初始化SharedPreferences:
object RetrofitInstance { private const val API_BASE_URL = BuildConfig.API_BASE_URL private val sharedPreferences: SharedPreferences by lazy { MyApp.instance.getSharedPreferences( MyApp.instance.getString(R.string.preference_file_key), Context.MODE_PRIVATE ) } private val httpBuilder: OkHttpClient.Builder get() { val httpClient = OkHttpClient.Builder() .addInterceptor(Interceptor { chain -> val original = chain.request() val bearerToken = sharedPreferences.getString( MyApp.instance.getString(R.string.preference_token_data_key), null ) val requestBuilder = original.newBuilder() .header("Accept", "application/json") // 仅当token不为空时添加Authorization头,避免无效请求 bearerToken?.takeIf { it.isNotBlank() }?.let { requestBuilder.header("Authorization", "Bearer $it") } return@Interceptor chain.proceed(requestBuilder.build()) }) return httpClient } private val retrofit by lazy { Retrofit.Builder() .baseUrl(API_BASE_URL) .client(httpBuilder.build()) .addConverterFactory( MoshiConverterFactory.create( Moshi.Builder().add(KotlinJsonAdapterFactory()).build() ) ) .addCallAdapterFactory(ResultCallAdapterFactory()) .build() } val api: TestService by lazy { retrofit.create(TestService::class.java) } }
关键优化点
- 安全获取Context:通过全局
MyApp.instance获取Application Context,确保Context始终有效且不为空 - 避免无效请求头:添加token前先判断是否非空非空白,防止发送
Bearer null这种无效的Authorization头 - 符合Android组件规则:不再让Retrofit单例继承Application,遵循Android的组件初始化逻辑
内容的提问来源于stack exchange,提问作者Yuhi
相关产品推荐
相关产品推荐

