You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动