Retrofit2中Chuck的使用及ChuckInterceptor的Context配置问题
如何在Retrofit2的OkHttpClient中正确传入Context到ChuckInterceptor
你遇到的核心问题是单例类Parser无法获取到MainActivity的Context来初始化ChuckInterceptor,这里有两种安全且实用的解决方案:
方案1:修改Parser的单例方法,传入Context
直接在getInstance方法中接收Context参数,并且存储ApplicationContext(避免持有Activity引用导致内存泄漏),具体代码如下:
修改后的Parser类
public class Parser { private static Parser instance; private Context mAppContext; private Retrofit mRetrofit; private static final String API_URL = "你的API基础地址"; // 私有构造方法,只接收ApplicationContext private Parser(Context appContext) { this.mAppContext = appContext; initOkHttpClientAndRetrofit(); } // 对外暴露的单例获取方法,传入任意Context即可 public static Parser getInstance(Context context) { if (instance == null) { synchronized (Parser.class) { if (instance == null) { // 转换为ApplicationContext,避免内存泄漏 instance = new Parser(context.getApplicationContext()); } } } return instance; } private void initOkHttpClientAndRetrofit() { OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(1, TimeUnit.MINUTES) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) // 使用存储的ApplicationContext初始化ChuckInterceptor .addInterceptor(new ChuckInterceptor(mAppContext)) .build(); mRetrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); } // 你的getInfo方法,返回对应的API Service public ApiService getInfo() { return mRetrofit.create(ApiService.class); } }
在MainActivity中调用
Parser.getInstance(MainActivity.this).getInfo().getUpdate(check).enqueue(new Callback<MobileCheck>() { @Override public void onResponse(Call<MobileCheck> call, retrofit2.Response<MobileCheck> response) { mobileCheck = response.body(); mainPresenter.enterApplication(false, true, mobileCheck.getResult().getUpdate(), mobileCheck.getResult().getUpgrade()); } @Override public void onFailure(Call<MobileCheck> call, Throwable t) { Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show(); } });
方案2:在Application类中全局初始化Parser
如果不想每次调用getInstance都传Context,可以在自定义Application的onCreate方法中完成初始化,这样整个App生命周期内都能直接使用单例:
1. 创建自定义Application类
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // 用ApplicationContext初始化Parser Parser.init(getApplicationContext()); } }
记得在AndroidManifest.xml中指定这个Application:
<application android:name=".MyApplication" <!-- 其他配置 --> > </application>
2. 修改Parser类
public class Parser { private static Parser instance; private Context mAppContext; private Retrofit mRetrofit; private static final String API_URL = "你的API基础地址"; private Parser(Context appContext) { this.mAppContext = appContext; initOkHttpClientAndRetrofit(); } // 全局初始化方法,只需要调用一次 public static void init(Context appContext) { if (instance == null) { synchronized (Parser.class) { if (instance == null) { instance = new Parser(appContext); } } } } // 直接获取单例,无需传参 public static Parser getInstance() { if (instance == null) { throw new IllegalStateException("请先在Application中调用Parser.init()初始化!"); } return instance; } private void initOkHttpClientAndRetrofit() { OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(1, TimeUnit.MINUTES) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .addInterceptor(new ChuckInterceptor(mAppContext)) .build(); mRetrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); } public ApiService getInfo() { return mRetrofit.create(ApiService.class); } }
3. 在MainActivity中调用
Parser.getInstance().getInfo().getUpdate(check).enqueue(new Callback<MobileCheck>() { // 回调逻辑不变 });
关键注意事项
- 永远使用
ApplicationContext:不要直接持有Activity的Context,因为ChuckInterceptor会和OkHttpClient绑定,生命周期可能远长于Activity,使用ApplicationContext可以避免内存泄漏问题。 - 如果在Fragment中调用,同样传递
getActivity().getApplicationContext()或者直接使用Parser.getInstance()(方案2)。
内容的提问来源于stack exchange,提问作者Temur Musurmanov




