项目的网络请求开发中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

相关文章

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

使用Java将实体类转换为JSON并输出到控制台的完整过程

《使用Java将实体类转换为JSON并输出到控制台的完整过程》在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用JSON格式,用Java将实体类转换为J... 在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用j

Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例

《Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例》本文介绍Nginx+Keepalived实现Web集群高可用负载均衡的部署与测试,涵盖架构设计、环境配置、健康检查、... 目录前言一、架构设计二、环境准备三、案例部署配置 前端 Keepalived配置 前端 Nginx

SQL Server中的PIVOT与UNPIVOT用法具体示例详解

《SQLServer中的PIVOT与UNPIVOT用法具体示例详解》这篇文章主要给大家介绍了关于SQLServer中的PIVOT与UNPIVOT用法的具体示例,SQLServer中PIVOT和U... 目录引言一、PIVOT:将行转换为列核心作用语法结构实战示例二、UNPIVOT:将列编程转换为行核心作用语

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs