OkHttp+Retrofit 使用示例
添加依赖
项目或 module 下的 build.gradle 文件添加如下依赖
dependencies { ... // rxandroid api 'io.reactivex.rxjava2:rxandroid:2.1.1' api 'io.reactivex.rxjava2:rxjava:2.2.19' // okhttp api 'com.squareup.okhttp3:okhttp:4.11.0' api 'com.squareup.okio:okio:3.2.0' api 'com.squareup.okhttp3:logging-interceptor:4.12.0' // retrofit api 'com.squareup.retrofit2:retrofit:2.9.0' api 'com.squareup.retrofit2:converter-moshi:2.9.0' api 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' api 'com.squareup.retrofit2:converter-gson:2.9.0'}配置 OkHttp、Retrofit
OkHttp 的管理类
/** * @Des OkHttp 配置 * @Author lipengfei * @Date 2023/11/27 18:06 */public class OkHttpFamily { private static final String TAG = OkHttpFamily.class.getSimpleName(); private static volatile OkHttpClient API; private OkHttpFamily() { } public static OkHttpClient API() { if (null == API) { synchronized (TAG) { if (null == API) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(15L, TimeUnit.SECONDS) .writeTimeout(15L, TimeUnit.SECONDS) .readTimeout(15L, TimeUnit.SECONDS); builder.addInterceptor(logging); for (Interceptor interceptor : HttpConfig.INSTANCE.getConfig().getInterceptors()) { builder.addInterceptor(interceptor); Log.i(TAG, "addInterceptor" + interceptor.getClass().getSimpleName()); } API = builder.build(); } } } return API; }}Retrofit 的管理类
/** * @Des Retrofit 配置 [单例] * @Author lipengfei * @Date 2023/11/27 18:06 */public class RetrofitFamily { private static Retrofit retrofit; // 使用 map 缓存已存在的 private static final Map<Class<?>, Object> SERVICE_MAP = new ConcurrentHashMap<>(); private RetrofitFamily() { } public static synchronized Retrofit getInstance() { if (null == retrofit) { retrofit = new Retrofit.Builder() .client(OkHttpFamily.API()) .baseUrl(HttpConfig.INSTANCE.getConfig().getBaseUrl()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } /** * 创建 Retrofit service。 */ public static <T> T createService(@NonNull Class<T> service) { T serviceImpl = (T) SERVICE_MAP.get(service); if (null == serviceImpl) { serviceImpl = createService(getInstance(), service); SERVICE_MAP.put(service, serviceImpl); } return serviceImpl; } private static <T> T createService(Retrofit retrofit, Class<T> service) { return retrofit.create(service); } /** * 切换环境后重置 */ static synchronized void reset() { retrofit = null; SERVICE_MAP.clear(); }} 网络请求相关的配置放入一个统一的文件
/** * @Des 请求配置统一管理 * @Author lipengfei * @Date 2023/11/27 18:06 */object HttpConfig { var config: Config? = null fun initConfig(config: Config) { this.config = config } class Config private constructor(val baseUrl: String, val interceptors: ArrayList<Interceptor>) { companion object { inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build() } class Builder { var baseUrl: String = "" private val interceptors: ArrayList<Interceptor> = ArrayList() fun addInterceptor(interceptor: Interceptor) { interceptors.add(interceptor) } fun build() = Config(baseUrl, interceptors) } }}发起第一个接口请求
在 app 启动时对 http 请求进行初始化配置
class MyApplication : Application() { override fun onCreate() { super.onCreate() initHttpConfig() } private fun initHttpConfig() { val config = HttpConfig.Config.build { // 设置 baseUrl this.baseUrl = ConfigC.PEXELS_BASE_URL // 设置 拦截器 this.addInterceptor(CommonInterceptor()) } // 需要在第一个接口请求发起之前配置,也可以做延迟处理 HttpConfig.initConfig(config) }}发起网络请求
class RPhotosViewModel : BaseViewModel() { val photosLiveData = MutableLiveData<Result<List<Photo>>>() fun searchPhotos() { if (photosLiveData.value is Result.Loading) { return } photosLiveData.value = Result.Loading compositeDisposable.add( RetrofitFamily.createService(PexelsApi::class.java) .searchPhotos("art", 1, ConstC.PAGE_COUNT_TEN).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ debug("success: photos.size=${it.photos.size}") photosLiveData.value = Result.Success(it.photos) }) { onError: Throwable? -> error("fail:", onError) photosLiveData.value = Result.Error(null, onError?.message) }) }}Activity/Fragment 中做对应的 UI 展示
viewModel.photosLiveData.observe(this) { when (it) { is Result.Loading -> { showLoading() } is Result.Success -> { hideLoading() photoAdapter.setDatas(it.value) } is Result.Error, Result.NetworkError -> { hideLoading() toast("error") } } }这样一个完整的接口请求就完成了
代码链接