终于到了Retrofit的总结的博客了,其实学网络这块是因为写项目时候,UI基本弄完了,和后台交互时候发行自己网络请求这块很不好,然后大佬让我直接学下Retrofit框架,但是一开始看的时候一脸懵逼,所以先学了网络基础知识,然后是安卓网络HTTPURLConnection基础类,接着是okhttp的学习,最后才开始学Retrofit的相关知识,才慢慢看懂,所以说知识是层层递进的,前面没掌握,后面肯定很懵逼。
Retrofit的介绍
http://square.github.io/retrofit/这个是它的官网教程,,,但是奈何英语不好,只能看别人博客,,,所以说英语还是蛮重要的哈
准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。
原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装
App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作
在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用户的需求对结果进行解析
感觉是在okhttp的基础上又进化了不少,封装了 数据转换、线程切换的操作
使用 Retrofit 的步骤共有7个:
步骤1:添加Retrofit库的依赖
步骤2:创建 接收服务器返回数据 的类
步骤3:创建 用于描述网络请求 的接口
步骤4:创建 Retrofit 实例
步骤5:创建 网络请求接口实例 并 配置网络请求参数
步骤6:发送网络请求(异步 / 同步)
优点:
1可以配置不同HTTP client来实现网络请求,如okhttp、httpclient等
2请求的方法参数注解都可以定制
3支持同步,异步,Rxjava
4可以配置不同的反序列化的工具解析数据,如json,xml
5方便灵活
缺点:
不能接触序列化实体和响应数据
执行的机制太严格
使用转换器比较低效
只能支持简单自定义参数类型
第一步:添加依赖和权限
老规矩了
在 build.gradle 文件中添加依赖,在 Manifest.xml文件中添加所需的网络权限。
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
// AndroidManifest.xml <uses-permission android:name="android.permission.INTERNET" />
第二步:创建用于网络请求的接口
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数
用 动态代理 动态 将该接口的注解“翻译”成一个 Http 请求,最后再执行 Http 请求
注:接口中的每个方法的参数都需要使用注解标注,否则会报错
public interface GetRequest_Interface { @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation> getCall();
// @GET注解的作用:采用Get方法发送网络请求
// getCall() = 接收网络请求数据的方法
// 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)
// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody> }
因为有好多的请求方式,下面分类来说,都是自己写的接口这块有差异
@GET、@POST、@PUT、@DELETE、@HEAD
以上方法分别对应 HTTP中的网络请求方式
// 第1部分:在网络请求接口的注解设置
@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation> getCall();
// 第2部分:在创建Retrofit实例时通过.baseUrl()设置
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://fanyi.youdao.com/") //设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.build();
// 从上面看出:一个请求的URL可以通过 替换块 和 请求方法的参数 来进行动态的URL更新。
// 替换块是由 被{}包裹起来的字符串构成
// 即:Retrofit支持动态改变网络请求根目录
Retrofit把 网络请求的URL 分成了两部分设置:基础地址+请求接口的注释
网络请求的完整 Url =在创建Retrofit实例时通过.baseUrl()设置 +网络请求接口的注解设置
等于说就是拼装请求网络地址,基础地址不能变,但是其他请求接口里面的地址可以动态设置,也可以固定的
@HTTP
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
public interface GetRequest_Interface {
/** * method:网络请求的方法(区分大小写)
* path:网络请求地址路径
* hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);
// {id} 表示是一个变量
// method 的值 retrofit 不会做处理,所以要自行保证准确 }
@FormUrlEncoded
作用:表示发送form-encoded的数据
每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
@Multipart作用:表示发送form-encoded的数据(适用于 有文件 上传的场景)
每个键值对需要用@Part来注解键名,随后的对象需要提供值。
@Header & @Headers
作用:添加请求头 &添加不固定的请求头
具体使用如下:
@Body
作用:以 Post方式 传递 自定义数据类型 给服务器
特别注意:如果提交的是一个Map,那么作用相当于 @Field
@Field & @FieldMap
作用:发送 Post请求 时提交请求的表单字段
具体使用:与 @FormUrlEncoded 注解配合使用
@Part & @PartMap
作用:发送 Post请求 时提交请求的表单字段
与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景
感觉这个真的是好全啊,各种网络请求的数据,方式都给你想好
第三步:创建返回数据的类
在第二步创建的接口里面有返回的数据类,所以自己必须定义好这个类,比如说
现在我声明好这个接口 只要传入一个字符串,然后返回一个Translation1类的对象
/**
* 有道翻译的数据类
*/
public class Translation1 {
private String type;
private int errorCode;
private int elapsedTime;
private List<List<TranslateResultBean>> translateResult;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public int getElapsedTime() {
return elapsedTime;
}
public void setElapsedTime(int elapsedTime) {
this.elapsedTime = elapsedTime;
}
public List<List<TranslateResultBean>> getTranslateResult() {
return translateResult;
}
public void setTranslateResult(List<List<TranslateResultBean>> translateResult) {
this.translateResult = translateResult;
}
public static class TranslateResultBean{
public String src;
public String tgt;
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getTgt() {
return tgt;
}
public void setTgt(String tgt) {
this.tgt = tgt;
}
}
}
第四步:创建Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/") // 设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
.build();
第五步:创建 网络请求接口实例
// 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
//对 发送请求 进行封装
Call<Reception> call = request.getCall();
第六步:发送网络请求
在里面封装了数据转换和线程切换,直接可以对控件数据更新
第七步:处理返回的数据
通过response类的 body()对返回的数据进行处理
RetrofitDome有道中英翻译
实现的功能:将 英文 翻译成 中文 或者 中文 翻译成英文
实现方法:采用Post方法对 有道API 发送网络请求
就是用有道的接口,获取要翻译的内容,然后拼装好网络请求地址,发送请求,获取返回的东西
采用 Gson 进行数据解析
1. 在 Gradle加入Retrofit库的依赖
2. 添加 网络权限
3. 创建 接收服务器返回数据 的类
API 的数据格式说明如下:
// URL http://fanyi.youdao.com/translate
// URL实例 http://fanyi.youdao.com/translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=
// 参数说明
// doctype:json 或 xml //
jsonversion:如果 doctype 值是 xml,则去除该值,若 doctype 值是 json,该值为空即可
// type:语言自动检测时为 null,为 null 时可为空。英译中为 EN2ZH_CN,中译英为 ZH_CN2EN,日译中为 JA2ZH_CN,中译日为 ZH_CN2JA,韩译中为 KR2ZH_CN,中译韩为 ZH_CN2KR,中译法为 ZH_CN2FR,法译中为 FR2ZH_CN
// keyform:mdict. + 版本号 + .手机平台。可为空
// model:手机型号。可为空
// mid:平台版本。可为空
// imei:???。可为空
// vendor:应用下载平台。可为空
// screen:屏幕宽高。可为空
// ssid:用户名。可为空
// abtest:???。可为空
// 请求方式说明
// 请求方式:POST
// 请求体:i
// 请求格式:x-www-form-urlencoded
所以说实体类按照上面的定义
/**
* 有道翻译的数据类
*/
public class Translation1 {
private String type;
private int errorCode;
private int elapsedTime;
private List<List<TranslateResultBean>> translateResult;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public int getElapsedTime() {
return elapsedTime;
}
public void setElapsedTime(int elapsedTime) {
this.elapsedTime = elapsedTime;
}
public List<List<TranslateResultBean>> getTranslateResult() {
return translateResult;
}
public void setTranslateResult(List<List<TranslateResultBean>> translateResult) {
this.translateResult = translateResult;
}
public static class TranslateResultBean{
public String src;
public String tgt;
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getTgt() {
return tgt;
}
public void setTgt(String tgt) {
this.tgt = tgt;
}
}
}
第四步:定义网络接口
/**
* postq请求的接口
*/
public interface PostRequest_Interface {
@POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=")
@FormUrlEncoded
Call<Translation1> getCall(@Field("i") String targetSentence);
}
第五步:xml界面
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="80dp" />
<Button
android:id="@+id/btn"
android:text="翻译"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
第六步:MainActivity
public class MainActivity extends AppCompatActivity {
private Context mcontext = this;
private TextView textView;
private EditText editText;
private Button bt;
private String s;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
textView = (TextView)findViewById(R.id.iv_show);
editText = (EditText)findViewById(R.id.et);
bt = (Button)findViewById(R.id.btn);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
s = editText.getText().toString();
if (s!=null){
requestpost();
}
}
});
}
/**
* 这个是post的
*/
public void requestpost(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
PostRequest_Interface postRequestInterface = retrofit.create(PostRequest_Interface.class);
Call<Translation1> call = postRequestInterface.getCall(s);
call.enqueue(new Callback<Translation1>() {
@Override
public void onResponse(Call<Translation1> call, Response<Translation1> response) {
String s = response.body().getTranslateResult().get(0).get(0).getTgt();
textView.setText(s);
}
@Override
public void onFailure(Call<Translation1> call, Throwable t) {
}
});
}
}
总结
终于是Retrofit的入门了,一开始看一脸懵逼,都不知道那些注释都是什么鬼,请求接口是干嘛的,但把之前基础东西看懂,慢慢就入门了,下周写项目时候再实战练习下这个网络框架。
https://github.com/sakurakid/RetrofitDoem Doem地址 希望可以帮到别人