由于以前Android开发第三方库总结的文章在交流群分享广受好评,就有很多朋友让我推荐对应的功能库。想着,既然你们都以为不错,那也想着顺手把本身经常使用的这些功能库给整理出来,从此要是问我怎么用,直接甩文章。哈哈哈,想一想都开心。java
本文面向对象:有必定基础的Android开发者。android
本篇文章大体内容从以下三个方面讲进行讲解:git
固然,倘若各位以为内容写得很差,本人心态很差,不接受任何批评。仍是那句话:you can you up,no can no ……github
好了,话很少说,今天讲Retrofit。小板凳拿好,开始上课。坐后面的朋友请到前面来。json
Retrofit,英文翻译过来是翻新,改进的意思,光看名字很难联想到他的具体做用,官方给的解释是:Type-safe HTTP client for Android and Java by Square,翻译过来就是由Square公司开发的一款针对Android网络请求的框架,底层是基于OkHttp的。retrofit github地址api
在Android开发过程当中,有不少的网络请求框架,好比Volley、Async Http Client,咱们为何要用Retrofit?bash
为何要用?一个词描述:方便。使用方便,修改也方便。网络
Retrofit的优势:app
缺点:框架
当前文章编写时最新版本为2.6.1。导包时到github去导入最新版本便可。
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
复制代码
Retrofit有一系列的辅助包,当咱们在导包的时候须要根据咱们的数据返回导入对应的包,不然会报异常: Could not locate ResponseBody converter for ……
好比咱们须要经过Gson转对象,咱们须要增长以下Gson转换辅助包:
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
复制代码
若是咱们使用了protobuf格式,那咱们须要添加protobuf转换辅助包:
implementation 'com.squareup.retrofit2:converter-protobuf:2.6.2'
复制代码
固然,还有不少辅助包:好比guava,jackson,jaxb,moshi,scalars等一系列辅助包,固然,这些在retrofit的retrofit-converters包下都有,有兴趣的能够去深刻了解。这里也列出来供你们导入。
Gson: compile 'com.squareup.retrofit2:converter-gson:2.6.2'
Jackson: compile 'com.squareup.retrofit2:converter-jackson:2.6.2'
Moshi: compile 'com.squareup.retrofit2:converter-moshi:2.6.2'
Protobuf: compile 'com.squareup.retrofit2:converter-protobuf:2.6.2'
Wire: compile 'com.squareup.retrofit2:converter-wire:2.6.2'
Simple XML: compile 'com.squareup.retrofit2:converter-simplexml:2.6.2'
Scalars (primitives, boxed, and String): compile 'com.squareup.retrofit2:converter-scalars:2.6.2'
复制代码
导完包以后,我们记得在AndroidManifest.xml中声明网络请求权限,添加以下代码便可申请网络请求权限。
<uses-permission android:name="android.permission.INTERNET" />
复制代码
好了,准备工做作完了,开始讲使用步骤吧。
这里咱们直接用官方给的例子来作示范:
public interface IGitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
复制代码
public class Repo {
……//其余属性
private String name;
public String getName() {
return name;
}
}
复制代码
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
IGitHubService service = retrofit.create(IGitHubService.class);
Call<List<Repo>> listRepos = service.listRepos("aserbao");
复制代码
listRepos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
updateUi(response.body());//返回处理
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
复制代码
固然,有一些特殊状况,这里也提一下:
当建立装换对象中的字符不能使用时,咱们可使用annotations注解来解决这个问题。举一个例子:json返回字段中若返回private属性,众所周知private不能在Android中当属性名,那这时候怎么办呢?能够这样作:
@com.google.gson.annotations.SerializedName("private")
private boolean privateX;
复制代码
好了,接下来介绍下Api的使用吧,Api的使用官方介绍也挺详细的,这里就做下简单介绍。
上面使用案例中咱们用了两个注解,分别是@GET和@Path,他们的做用是什么呢?是否有其余注解,接下来我们一块儿去了解下Retrofit中的诸多注解以及他们的做用。
第一类:网络请求注解
用于网络请求方式的注解,好比@GET注解的就是经过get请求接口,@Post注解标记的就是经过post请求接口。相似的是还有@PUT、@DELETE、@HEAD(经常使用)。做用相同。很少叙述。
固然,在网络请求注解中有一个特殊注解:@HTTP,这个注解相似于一个融合器,他能够在使用上述请求的同时,并进行扩展配置。好比咱们经过@HTTP配置一个Get请求,且配置body,那咱们能够这样配置:
@HTTP(method = "GET",path = "{user}/repos", hasBody = true)
Call<List<Repo>> listRepos3(@Path("user") String user);
复制代码
固然,若是不知道如何使用,直接点到HTTP接口的源码中查看,注释里面便有具体使用案例。
第二类:网络请求标记注解 retrofit中的标记注解有是三个,分别是:@FormUrlEncoded、@Multipart、@Streaming,见名知意,我们也稍微解释下做用。
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
复制代码
@POST("/file")
@Multipart
Observable<DataResponse<UploadBean>> uploadFile(@Part("file\"; filename=\"aserbao.png\"") RequestBody file,@Part("name") RequestBody nickName);
复制代码
固然,@Multipart还能够经过@PartMap添加多个上传信息来实现一次上传多个文件。好比咱们须要上传aserbao/imgs这个目录下的全部图片,咱们能够这样实现。
@Multipart
@POST("/files")
Call<UploadBean> uploadFiles(@PartMap Map<String, RequestBody> params);
String aserbao_path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/aserbao/imgs/";
File file1 = new File(aserbao_path);
if (!file1.exists()) return;
Map<String, RequestBody> partMap = new HashMap<>();
for (File file : file1) {
RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);
partMap.put("file\"; filename=\"" + file.getName() + "\"", fileBody);
}
……
复制代码
第三类:网络请求参数注解
这类注解也是使用最多的一类,下面我们来一块儿了解下:
//@Header做用在参数上
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
//@Headers做用在方法上
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
//@HeaderMap经过键值对的方式给参数添加请求头
@GET("user")
Call<User> getUser(@HeaderMap Map<String, String> headers)
复制代码
@POST("users/new")
Call<User> createUser(@Body User user);
复制代码
值得注意的是,当没有添加转换器的使用,@Body注释的对象只能是RequestBody。
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
复制代码
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
复制代码
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
复制代码
这里当咱们调用方法listRepos("aserbao")时,对应@GET中的values值就会变成users/aserbao/repos
@GET("/user/test")
Call<Test> testQuery(@Query("id") String id);
复制代码
调用testQuery(15),对应生成@GET中的values就是/user/test?id=15
@GET("https://api.github.com/users/aserbao/repos")
Call<List<Repo>> listAbsRepos();
@GET
Call<List<Repo>> listAbsRepos(@Url String url);
复制代码
Retfoit的注解有一个value的参数,好比@GET("users/{user}/repos")。固然不一样的baseUrl配置,value参数起的做用也是不一样的。
继续拿上面例子来讲,好比咱们要请求https://api.github.com/users/aserbao/repos这个url,咱们能够怎么配置呢?
第一种:baseUrl中只添加host也就是https://api.github.com/,后面的参数写在@GET注解里。
这里直接拿上面的例子中的代码就能够了。
new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build()
.create(IGitHubService.class)
.listRepos("aserbao");
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
复制代码
第二种:咱们在baseUrl中添加https://api.github.com/users/,后面的参数添加到values里面也能够。
new Retrofit.Builder()
.baseUrl("https://api.github.com/users/") //这里注意最后有添加/。
.build()
.create(IGitHubService.class)
.listRepos("aserbao");
@GET("{user}/repos")
Call<List<Repo>> listRepos2(@Path("user") String user);
复制代码
第三种:咱们能够直接将请求连接放到参数里面。,
new Retrofit.Builder()
.baseUrl("")//baseUrl里面能够填空
.build()
.create(IGitHubService.class)
.listAbsRepos();
@GET("https://api.github.com/users/aserbao/repos")
Call<List<Repo>> listAbsRepos();
复制代码
上面三种状况,在实际项目开发过程当中咱们使用的较多的仍是第一种。
特别注意:baseUrl中添加的连接最后必需要添加/符号,不然会报java.lang.IllegalArgumentException: baseUrl must end in / 的异常。
在请求的时候给设置请求拦截器是颇有必要的一步,不只可让咱们清楚的了解请求内容,快速定位请求过程当中遇到的问题。还能够经过拦截请求添加通用参数和头部字段。
那如何给Retrofit设置请求拦截器呢?前面也说了Retofit实际上市Okhttp的高度封装,Okhttp如何设置,Retrofit就怎么配置便可。固然,有兴趣想了解更多关于Okhttp的内容能够参考个人另一篇文章HTTP 网络请求库 OkHttp 的全面讲解。
好了,话很少说,我们来看Retrofit如何设置拦截器。
步骤以下:
class LoggingInterceptor implements Interceptor {
@Override public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
Log.e(TAG, String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
okhttp3.Response response = chain.proceed(request);
long t2 = System.nanoTime();
Log.e(TAG, String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
复制代码
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS)
//添加OkHttp3的拦截器
.addInterceptor(new LoggingInterceptor())
.writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS)
.build();
复制代码
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.baseUrl("https://api.github.com/users")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)//配置OkHttpClient
.build();
复制代码
经过上面的列子,咱们来看下请求运行后的拦截效果:
11-24 10:05:12.023 4671-4690/com.example.baseandroidframework E/RetrofitActivity: Received response for https://api.github.com/users/aserbao/repos in 2495.2ms
Date: Tue, 26 Nov 2019 01:36:31 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Server: GitHub.com
Status: 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1574735790
Cache-Control: public, max-age=60, s-maxage=60
Vary: Accept
ETag: W/"58bffa073ed17b36ffb324dd04f66539"
X-GitHub-Media-Type: github.v3; format=json
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Vary: Accept-Encoding
X-GitHub-Request-Id: D99C:7F00:4DADB:61266:5DDC819D
复制代码
好了,大功告成,咱们配置拦截器就这样完成了。
到这里,咱们的Retrofit的知识点算告一段落了,下面简单总结下
首先和你们一块儿来回顾下这篇文章的大体内容,主要讲了关于Retrofit的三个方面的内容,分别是:
其实经过文章咱们能够发现RetrofitAPI并很少,正如官方所言,他是一个关于OkHttp的高度封装库。
好了,文章到这里就要结束了,若是对本文有什么疑问或者不理解的地方,欢迎给我留言。固然,若是想系统性学Android,提高Android技术的朋友,能够关注个人我的公众号「aserbaocool」,加群讨论,一块儿学习交流Android。