安卓网络总结(五)--Retrofit的介绍和简单使用

终于到了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地址 希望可以帮到别人

猜你喜欢

转载自blog.csdn.net/sakurakider/article/details/80558273