Android--Retrofit浅入深出

2024-04-08 07:32
文章标签 android retrofit 浅入 深出

本文主要是介绍Android--Retrofit浅入深出,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

官网:http://square.github.io/retrofit/

官方定义:
A type-safe HTTP client for Android and Java

一:配置
app:build.gradle:

compile 'com.squareup.retrofit2:retrofit:2.0.2'

二:例子

–1:BaseResponse

public class BaseResponse {String returnCode;String msg;String result;boolean success;public String getReturnCode() {return returnCode;}public void setReturnCode(String returnCode) {this.returnCode = returnCode;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public boolean isSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}
}

–2:HtppService


public interface HttpService {@FormUrlEncoded@POST("/frist/noIntercept/user/login.do")Call<UserResponse> getUserByLogin(@Field("password") String password, @Field("phone") String phone);}

–3:User

public class User {private int id;private boolean invalid;private int status;private long createdDatetime;private long updatedDatetime;private int orderTag;private String name;private String phone;private String password;private String slogan;private String imagpath;private int userid;private int sex;public int getId() {return id;}public void setId(int id) {this.id = id;}public boolean isInvalid() {return invalid;}public void setInvalid(boolean invalid) {this.invalid = invalid;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public long getCreatedDatetime() {return createdDatetime;}public void setCreatedDatetime(long createdDatetime) {this.createdDatetime = createdDatetime;}public long getUpdatedDatetime() {return updatedDatetime;}public void setUpdatedDatetime(long updatedDatetime) {this.updatedDatetime = updatedDatetime;}public int getOrderTag() {return orderTag;}public void setOrderTag(int orderTag) {this.orderTag = orderTag;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getSlogan() {return slogan;}public void setSlogan(String slogan) {this.slogan = slogan;}public String getImagpath() {return imagpath;}public void setImagpath(String imagpath) {this.imagpath = imagpath;}public int getUserid() {return userid;}public void setUserid(int userid) {this.userid = userid;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}
}

–4:BaseResponse

public class UserResponse extends BaseResponse {private RespData data;public RespData getData() {return data;}public void setData(RespData data) {this.data = data;}public static class RespData {private User user;public User getUser() {return user;}public void setUser(User user) {this.user = user;}}
}

–5:MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener { 
private static final String WEB_URL = "http://192.168.1.115:8080";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.start).setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.start:getUser();break;}}private void getUser() {Retrofit retrofit = new Retrofit.Builder().baseUrl(WEB_URL).addConverterFactory(GsonConverterFactory.create()).build();HttpService httpService = retrofit.create(HttpService.class);String phone = "15029206553";String password = "123456";Call<UserResponse> call = httpService.getUserByLogin(password, phone);call.enqueue(new Callback<UserResponse>() {@Overridepublic void onResponse(Call<UserResponse> call, Response<UserResponse> response) {Toast.makeText(MainActivity.this, "respone" + response.body().getData().getUser().getImagpath(), Toast.LENGTH_LONG).show();}@Overridepublic void onFailure(Call<UserResponse> call, Throwable t) {}});}
}

注:可以看出,接口返回的是需要的JAVA对象,不是而不是byte[]或String!Retrofit内部默认使用Gson解析相关数据。

三:相关方法:

—-1:支持:GET, POST, PUT, DELETE, and HEAD!

@GET("users/list")
@GET("/frist/noIntercept/user/login.do")
Call<UserResponse> getUserByLogin(@Query("password") String password, @Query("phone") String phone);

也可以直接在请求接口中显示需要的参数,类似于:

@GET("users/list?sort=desc")
@GET("/frist/noIntercept/user/login.do?password=123456&phone=15029206553")
Call<UserResponse> getUserByLogin();

使用技巧:当我们使用POST方式无参去请求数据的时候,请修改为无参的GET请求。
- - 2:可以动态更新请求块里面的参数和方法,一个相应的参数必须和@Path保持同样的字符串

 @GET("group/{id}/users")Call<List<User>> groupList(@Path("id") int groupId);
@GET("/frist/noIntercept/{user}/login.do?password=123456&phone=15029206553")
Call<UserResponse> getUserByLogin(@Path("user") String user);

也可以使用查询方法来添加相关参数,类似于:

 @GET("group/{id}/users")Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
@GET("/frist/noIntercept/{user}/login.do")
Call<UserResponse> getUserByLogin(@Path("user") String user,@Query("password") String password, @Query("phone") String phone);

—-3:Map使用

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

使用技巧:对于复杂参数,可以使用Map来组合请求对象。

—-4:JavaBean作为请求体<添加转换器,若没有添加,只能使用response>

@POST("users/new")Call<User> createUser(@Body User user);
public class LoginBean {String password;String phone;public  LoginBean(String password, String phone){this.password=password;this.phone=phone;}
}@POST("/frist/noIntercept/user/login.do")
Call<UserResponse> getUserByLogin(@Body LoginBean loginBean);
String phone = "15029206553";
String password = "123456";
LoginBean loginBean=new LoginBean(password,phone);
Call<UserResponse> call = httpService.getUserByLogin(loginBean);

注意点:使用此种方式传参,需要修改后台正常获取参数的方式,慎用。

—-5:指定请求编码类型

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
@FormUrlEncoded
@POST("/frist/noIntercept/user/login.do")
Call<UserResponse> getUserByLogin(@Field("password") String password, @Field("phone") String phone);

—-6:操作Head

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

也可以写成下面:

@Headers({"Accept: application/vnd.github.v3.full+json","User-Agent: Retrofit-Sample-App"})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);

注:当@Headers{}为空时,则会自动忽略。

—-7:每个请求都添加Head:<动态更新>

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

—-8:使用ConverterFactory来修改默认返回数据解析<可自定义转换器>
Retrofit默认使用GSON进行相关数据解析。

这里写图片描述

下面是一个使用GsonConverterFactory生成JSON解析数据的例子:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com").addConverterFactory(GsonConverterFactory.create()).build();
GitHubService service = retrofit.create(GitHubService.class);

四:简单封装:
–1:RetrofitUtil:

public class RetrofitUtil {private static final String WEB_URL = "http://192.168.1.115:8080";public static HttpService instanceHttpService() {Retrofit retrofit = new Retrofit.Builder().baseUrl(WEB_URL).addConverterFactory(GsonConverterFactory.create()).build();HttpService httpService = retrofit.create(HttpService.class);return httpService;}
}

–2:MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.start).setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.start:getUser();break;}}private void getUser() {String phone = "15029206553";String password = "123456";Call<UserResponse> call = RetrofitUtil.instanceHttpService().getUserByLogin(password, phone);call.enqueue(new Callback<UserResponse>() {@Overridepublic void onResponse(Call<UserResponse> call, Response<UserResponse> response) {Toast.makeText(MainActivity.this, "respone" + response.body().getData().getUser().getImagpath(), Toast.LENGTH_LONG).show();}@Overridepublic void onFailure(Call<UserResponse> call, Throwable t) {}});}
}

可以看出来:代码量减少很多。

五:深度封装:
拦截器是一个强大的机制,可以监视,重写,然后重新调用。
–1:
调用链的调用(请求)是每个拦截的执行的一个关键部分:

public class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();long t1 = System.nanoTime();.....// request.url(), chain.connection(), request.headers();Response response = chain.proceed(request);long t2 = System.nanoTime();....// response.request().url(), (t2 - t1) / 1e6d, response.headers();return response;}
}

这里写图片描述

–2:Application interceptors:
—-:拦截器分为应用拦截和网络:
打印拦截器:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(logging)//添加打印拦截器.connectTimeout(30, TimeUnit.SECONDS)//设置请求超时时间.retryOnConnectionFailure(true)//设置出现错误进行重新连接。.build();
注意:多了一个.client()方法:
Retrofit retrofit = new Retrofit.Builder().baseUrl(WEB_URL).client(httpClient).addConverterFactory(GsonConverterFactory.create()).build();

因为OKHTTP支持重定向,而Retrofit是基于OKHTTP3建立各种模块的。

–3:重定向

OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()).build();Request request = new Request.Builder().url("http://www.publicobject.com/helloworld.txt").header("User-Agent", "OkHttp Example").build();Response response = client.newCall(request).execute();
response.body().close();

结果为:

INFO: Sending request http://www.publicobject.com/helloworld.txt on null
User-Agent: OkHttp ExampleINFO: Received response for https://publicobject.com/helloworld.txt in 1179.7ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

–4:网络监听器

.addNetworkInterceptor(new LoggingInterceptor())

应用和网络拦截器比对:

应用拦截器:
--1:不用担心请求时重定向和定向次数
--2:调用次数为一次<缓存>
--3:允许重试,多次调用请求链<okhttp请求是通过链路进行管理的>
--4:可以观察应用的意图,在请求或者返回数据的时候进行相关匹配以及处理
网络拦截器:
--1:观察数据传输

六:特殊需求:
–1:所有网络请求都添加token:

Interceptor mToken = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request originalRequest = chain.request();if (You.token == null || alreadyHasAuthorizationHeader(originalRequest)) {return chain.proceed(originalRequest);}Request authorised = originalRequest.newBuilder().header("Authorization", You.token).build();return chain.proceed(authorised);}
};public static boolean alreadyHasAuthorizationHeader(Request request) {if (request != null) {if (request.headers() != null) {return true;} else {return false;}}return false;
}

–1:
—-:if判断,当你有token的时候才会进行添加,或者请求验证中已经有hrader了,那么就不执行这个token了。
—-:header 的 key 通常是 Authorization,可以修改

2–:添加公私密钥

MarvelSigningInterceptor signingInterceptor = new MarvelSigningInterceptor(KeyValue.MARVEL_PUBLIC_KEY, KeyValue.MARVEL_PRIVATE_KEY);

3–:添加缓存策略

File cacheFile = new File(context.getCacheDir(), "ZhiBookCache");Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);Interceptor interceptorCache = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();if (!NetworkStateUtils.getInstance(context).isConnection()) {request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();}Response response = chain.proceed(request);if (NetworkStateUtils.getInstance(context).isConnection()) {int maxAge = 0 * 60;// 有网络时 设置缓存超时时间0个小时response.newBuilder().header("Cache-Control", "public, max-age=" + maxAge).removeHeader("Pragma")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效.build();} else {// 无网络时,设置超时为4周int maxStale = 60 * 60 * 24 * 28;response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale).removeHeader("Pragma").build();}return response;}};

七:再次封装:
–1:

public abstract class RCllBack<T> implements Callback<T> {@Overridepublic void onResponse(Call<T> call, Response<T> response) {onSuccess(response.body());}@Overridepublic void onFailure(Call<T> call, Throwable t) {}public abstract void onSuccess(T response);
}

–2:

public abstract class RCllBaackComm<T> implements Callback<T> {@Overridepublic void onResponse(Call<T> call, Response<T> response) {BaseResponse resp = (BaseResponse) response.body();//在此可以根据自己的功能需求进行相关判断}@Overridepublic void onFailure(Call<T> call, Throwable t) {onFailed(new CommError("网络错误"));}public abstract void onSuccess(T response);public abstract void onFailed(CommError error);}

概念理解:

onResponse: HTTP有效也就是请求返回为200,返回数据
因此在此方法里面,可以根据自己和服务器返回值的约定进行相关处理;

onFailure:当请求地址不存在或者其他原因<无网络>

以下为三种不同方法用起来的差异:

Call<UserResponse> call = RetrofitUtil.service.getUserByLogin(password, phone);
//1
call.enqueue(new Callback<UserResponse>() {@Overridepublic void onResponse(Call<UserResponse> call, Response<UserResponse> response) {Toast.makeText(MainActivity.this, "respone" + response.body().getData().getUser().getImagpath(), Toast.LENGTH_LONG).show();}@Overridepublic void onFailure(Call<UserResponse> call, Throwable t) {}
});
//2
call.enqueue(new RCllBack<UserResponse>() {@Overridepublic void onSuccess(UserResponse response) {}
});
//3
call.enqueue(new RCllBaackComm<UserResponse>() {@Overridepublic void onSuccess(UserResponse response) {}@Overridepublic void onFailed(CommError error) {}
});

相关依赖引入:

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.0.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'

本次源码获取地址:
github:https://github.com/erhutime/NetWorking

这篇关于Android--Retrofit浅入深出的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl