项目的网络请求开发中retrofit2和okhttp3的结合使用示例

2023-12-15 14:58

本文主要是介绍项目的网络请求开发中retrofit2和okhttp3的结合使用示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文是retrofit2和okhttp3的结合使用的简单示例,逻辑不复杂,示例代码中使用的框架版本是okhttp:4.4.0和retrofit:2.7.2,下文将贴出所有代码:

项目结构:

AndroidManifest的配置: 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.windfallsheng.retrofitandokhttpexample"><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission><uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission><!--用于访问网络--><uses-permission android:name="android.permission.INTERNET"></uses-permission><applicationandroid:name=".MySupportApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

build.gradle的配置内容:

apply plugin: 'com.android.application'android {compileSdkVersion 28defaultConfig {applicationId "com.windfallsheng.retrofitandokhttpexample"minSdkVersion 16targetSdkVersion 28versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])implementation 'com.android.support:appcompat-v7:28.0.0'implementation 'com.android.support.constraint:constraint-layout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'com.android.support.test:runner:1.0.2'androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'// 加入依赖implementation "com.squareup.okhttp3:okhttp:4.4.0"implementation "com.squareup.okhttp3:logging-interceptor:4.4.0"implementation "com.squareup.retrofit2:retrofit:2.7.2"implementation "com.squareup.retrofit2:converter-gson:2.7.2"implementation "com.google.code.gson:gson:2.8.6"
}

 使用:

package com.windfallsheng.retrofitandokhttpexample;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.windfallsheng.retrofitandokhttpexample.net.Param;
import com.windfallsheng.retrofitandokhttpexample.net.ResponseEntity;
import com.windfallsheng.retrofitandokhttpexample.net.RetrofitManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;public class MainActivity extends AppCompatActivity {private static final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 设置请求参数的过程;List<Param> paramList = new ArrayList<>();paramList.add(new Param("sex", "0"));paramList.add(new Param("age", "25"));Map paramMap = new HashMap();for (Param param : paramList) {paramMap.put(param.getKey(), param.getValue());}Call call = RetrofitManager.getDefault(ServerHost.USER_INFO).getUserList(RetrofitManager.getCacheControl(), paramMap);// 开始网络请求:call.enqueue(new Callback<ResponseEntity>() {@Overridepublic void onResponse(retrofit2.Call<ResponseEntity> call, Response<ResponseEntity> response) {Log.d(TAG, "method:login#onResponse#response.isSuccessful=" + response.isSuccessful());if (response.isSuccessful()) {Log.d(TAG, "method:login#onResponse#ResponseEntity=" + response.body());}}@Overridepublic void onFailure(retrofit2.Call call, Throwable t) {Log.d(TAG, "method:login#onFailure#t=" + t);}});}
}

接口定义:

package com.windfallsheng.retrofitandokhttpexample.net;import android.database.Observable;
import java.util.Map;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.Header;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PartMap;/*** @author lzsheng 请求接口;*/
public interface APIService {@FormUrlEncoded@POST("mobileuser/login")Observable<ResponseEntity> login(@Header("Cache-Control") String cacheControl, @Field("phoneNumber") String account,@Field("password") String password);@Multipart@POST("mobileuser/register")Observable<ResponseEntity> registe(@PartMap Map<String, RequestBody> multipartMap);@FormUrlEncoded@POST("mobileuser/userlist")Call<ResponseEntity> getUserList(@Header("Cache-Control") String cacheControl, @FieldMap Map<String, String> params);}

网络请求及初始化配置管理类:

package com.windfallsheng.retrofitandokhttpexample.net;import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.windfallsheng.retrofitandokhttpexample.MySupportApplication;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;/*** 缓存设置* 1. noCache 不使用缓存,全部走网络* 2. noStore 不使用缓存,也不存储缓存* 3. onlyIfCached 只使用缓存* 4. maxAge 设置最大失效时间,失效则不使用 需要服务器配合* 5. maxStale 设置最大失效时间,失效则不使用 需要服务器配合* 6. minFresh 设置有效时间,依旧如上* 7. FORCE_NETWORK 只走网络* 8. FORCE_CACHE 只走缓存*/
public class RetrofitManager {private static final String TAG = "RetrofitManager";//读超时长,单位:毫秒public static final int READ_TIME_OUT = 7676;//连接时长,单位:毫秒public static final int CONNECT_TIME_OUT = 7676;public Retrofit mRetrofit;public APIService mAPIService;public OkHttpClient mOkHttpClient;private static SparseArray<RetrofitManager> sRetrofitManager = new SparseArray<>(ServerHost.values().length);/*** 设缓存有效期为两天*/private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;/*** 查询缓存的Cache-Control设置,为if-only-cache时只查询缓存而不会请求服务器,max-stale可以配合设置缓存失效时间* max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可接收超出超时期指定值之内的响应消息。*/private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;/*** 查询网络的Cache-Control设置,头部Cache-Control设为max-age=0* (假如请求了服务器并在a时刻返回响应结果,则在max-age规定的秒数内,浏览器将不会发送对应的请求到服务器,数据由缓存直接返回)时则不会使用缓存而请求服务器*/private static final String CACHE_CONTROL_AGE = "max-age=0";//构造方法私有private RetrofitManager(String baseUrl) {//开启LogHttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//缓存File cacheFile = new File(MySupportApplication.getInstance().getCacheDir(), "cache");Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb//增加头部信息Interceptor headerInterceptor = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request build = chain.request().newBuilder().addHeader("Content-Type", "application/json").build();return chain.proceed(build);}};mOkHttpClient = new OkHttpClient.Builder().readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS).connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS).addInterceptor(mRewriteCacheControlInterceptor).addNetworkInterceptor(mRewriteCacheControlInterceptor).addInterceptor(headerInterceptor).addInterceptor(logInterceptor).cache(cache).build();Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").serializeNulls().create();mRetrofit = new Retrofit.Builder().client(mOkHttpClient).addConverterFactory(GsonConverterFactory.create(gson))
//                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).baseUrl(baseUrl).build();mAPIService = mRetrofit.create(APIService.class);}/*** @param serverHost {@link ServerHost}*/public static APIService getDefault(ServerHost serverHost) {Log.d(TAG, "method:getDefault#sRetrofitManager=" + sRetrofitManager);int hostType = serverHost.getHostType();RetrofitManager retrofitManager = sRetrofitManager.get(hostType);if (retrofitManager == null) {retrofitManager = new RetrofitManager(serverHost.getBaseUrl());sRetrofitManager.put(hostType, retrofitManager);}return retrofitManager.mAPIService;}/*** OkHttpClient** @return*/public static OkHttpClient getOkHttpClient(ServerHost serverHost) {int hostType = serverHost.getHostType();String baseUrl = serverHost.getBaseUrl();RetrofitManager retrofitManager = sRetrofitManager.get(hostType);if (retrofitManager == null) {retrofitManager = new RetrofitManager(baseUrl);sRetrofitManager.put(hostType, retrofitManager);}return retrofitManager.mOkHttpClient;}/*** 根据网络状况获取缓存的策略*/public static String getCacheControl() {return isNetworkAvailable(MySupportApplication.getInstance()) ? CACHE_CONTROL_AGE : CACHE_CONTROL_CACHE;}/*** 响应头拦截器,用来配置缓存策略* Dangerous interceptor that rewrites the server's cache-control header.*/private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();String cacheControl = request.cacheControl().toString();if (!isNetworkAvailable(MySupportApplication.getInstance())) {request = request.newBuilder().cacheControl(TextUtils.isEmpty(cacheControl) ? CacheControl.FORCE_NETWORK : CacheControl.FORCE_CACHE).build();}Response originalResponse = chain.proceed(request);if (isNetworkAvailable(MySupportApplication.getInstance())) {//有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置return originalResponse.newBuilder().header("Cache-Control", cacheControl).removeHeader("Pragma").build();} else {return originalResponse.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC).removeHeader("Pragma").build();}}};private static boolean isNetworkAvailable(Context context) {ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);if (connectivity != null) {//ACCESS_NETWORK_STATENetworkInfo info = connectivity.getActiveNetworkInfo();if (info != null && info.isConnected()) {// 当前网络是连接的if (info.getState() == NetworkInfo.State.CONNECTED) {// 当前所连接的网络可用return true;}}}return false;}}

 定义各host的枚举类:

package com.windfallsheng.retrofitandokhttpexample.net;/*** @author lzsheng host的枚举;*/
public enum ServerHost {USER_INFO(1, "http://192.*.*.*:8066/"), NEWS_FLASH(2, "https://192.*.*.*:8080/");private int hostType;private String baseUrl;private ServerHost(int type, String baseUrl) {this.hostType = type;this.baseUrl = baseUrl;}public int getHostType() {return hostType;}public void setHostType(int hostType) {this.hostType = hostType;}public String getBaseUrl() {return baseUrl;}public void setBaseUrl(String baseUrl) {this.baseUrl = baseUrl;}
}

其它相关类:

package com.windfallsheng.retrofitandokhttpexample;import android.app.Application;
import android.content.Context;public class MySupportApplication extends Application {private static Context mContext;@Overridepublic void onCreate() {super.onCreate();mContext = this;}public static Context getInstance() {return mContext;}
}
package com.windfallsheng.retrofitandokhttpexample.net;import com.google.gson.annotations.SerializedName;
import java.io.Serializable;/*** @Author: lzsheng* @Description: 网络请求的返回值实体类, 使用新版本Gson的jar包,修改注解 @SerializedName(value = "val",* alternate = {"alt1", "alt2"})* @Version:*/
public class ResponseEntity<T> implements Serializable {@SerializedName(value = "code", alternate = {"rt", "result"})private int resultCode;@SerializedName("success")private boolean isSuccess;@SerializedName(value = "msg", alternate = {"message", "content"})private String resultMsg;private T data;public int getResultCode() {return resultCode;}public void setResultCode(int resultCode) {this.resultCode = resultCode;}public boolean isSuccess() {return isSuccess;}public void setSuccess(boolean success) {isSuccess = success;}public String getResultMsg() {return resultMsg;}public void setResultMsg(String resultMsg) {this.resultMsg = resultMsg;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "ResponseEntity{" +"resultCode=" + resultCode +", isSuccess=" + isSuccess +", resultMsg='" + resultMsg + '\'' +", data=" + data +'}';}
}
package com.windfallsheng.retrofitandokhttpexample.net;/*** @author lzsheng 请求参数的键值对*/
public class Param {private String key;private String value;public Param() {}public Param(String key, String value) {super();this.key = key;this.value = value;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}@Overridepublic String toString() {return "Param [key=" + key + ", value=" + value + "]";}}

       有关网络请求相关业务的处理方式多种多样,根据自己的项目状态和业务需求,做相应的业务封闭即可,以上只是简单演示,不必苛责。

 

由于作者水平有限,语言描述及代码实现中难免有纰漏,望各位看官多提宝贵意见!

Hello , World !

感谢所有!

这篇关于项目的网络请求开发中retrofit2和okhttp3的结合使用示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/496853

相关文章

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提