每天学习一个Android中的常用框架——5.Retrofit

文章目录

  • 1.简介
  • 2.特性
  • 3.演示
    • 3.1 集成
    • 3.2 配置
    • 3.3 布局文件和URL封装
    • 3.5 GET请求——传统网络参数
    • 3.6 GET请求——RestFul风格
    • 3.7 POST请求
  • 4.源码地址

1.简介

在介绍Android中相关网络框架的时候,我们介绍过了Square公司制作的OkHttpOKIo。事实上,这两个框架配合使用的时候,基本上已经可以完成大部分的网络业务需求了。不过,学习是永远没有尽头的。这篇博客中,我们将介绍同样由Square公司制作,目前同样流行的另一个网络框架——Retrofit
Retrofit是一个现在比较火的网络请求框架,它的底层是依靠OkHttp实现的。确切的讲,Retrofit是对OkHttp的进一步封装,它的功能更加强大,支持同步和异步、支持多种数据的解析(默认使用Gson),也支持RxJava。
Retrofit的一个优势,就是简洁易用,它通过注解配置网络请求的参数,采用大量的设计模式来简化我们的使用。而且它的拓展性也做的相当的好,Retrofit的功能模块高度封装,高内聚低耦合,我们可以自定义自己想要的组件,比如说我们可以自己选择解析工具而不用默认的Gson,实现了高度的定制性。
除此之外,Retrofit还有诸如性能好,处理速度快,代码简化等优势,给足了理由让我们去尝试使用这款网络请求框架。

2.特性

在使用Retrofit之前,我们应该先了解它的特性。使用Retrofit的过程中,由于其大量注解开发的形式,我觉得十分类似于Java中的Spring MVC框架,通过标识专属的注解,就可以达到快速的配置和开发,一些Retrofit常见的方法注解如图所示:
每天学习一个Android中的常用框架——5.Retrofit_第1张图片
除此之外,一些常见的字段注解如图所示:
每天学习一个Android中的常用框架——5.Retrofit_第2张图片
将这些注解进行整理,可以得到一张大致的结构图:
每天学习一个Android中的常用框架——5.Retrofit_第3张图片
其中:

  1. 网络请求方法
    每天学习一个Android中的常用框架——5.Retrofit_第4张图片

  2. 标记类
    每天学习一个Android中的常用框架——5.Retrofit_第5张图片

  3. 网络请求参数
    每天学习一个Android中的常用框架——5.Retrofit_第6张图片

看到这么多的注解,是否有一种头晕目眩的感觉?没关系,在本篇博客中,只会演示比较常用的注解:@GET,@POST,@Path,@Query ,其他的代码可以根据需求进行相应地调用,调用过程是类似的,具体的api调用还是那句话:查看Retrofit官网获取更多的相关信息。

3.演示

3.1 集成

在使用任何框架之前,集成都是第一步。由于Retrofit已经用到了OkHttp,所以这里只需要导入Retrofit一个依赖即可,修改module下的build.gradle,代码如下:

implementation 'com.squareup.retrofit2:retrofit:2.8.1'

修改完成后Sync一下,确保Retrofit集成到了你的项目中。

3.2 配置

这里的配置主要是针对在使用Retrofit遇到的一个坑,简单提一下避免读者在使用的时候踩坑。
问题:导入Retrofit依赖后,在build工程后出现如图所示的错误
在这里插入图片描述
每天学习一个Android中的常用框架——5.Retrofit_第7张图片

原因:从出错原因可以很简单地看出,使用Retrofit需要你的Android版本最低达到Android O(即api 26),所以只需要修改有关此处的配置信息即可。
解决方法:在项目下的build.gradle文件添加一个compileOptions闭包,声明JDK版本,代码如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.androidframelearn.http_retrofit"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.squareup.retrofit2:retrofit:2.8.1'

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

3.3 布局文件和URL封装

接下来,我们直接开始布局文件activity_main.xml的编写。该布局很简单,仅有四个按钮,代码如下:


<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">

    <Button
        android:id="@+id/btn_get"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送get请求——通过http拼接网络参数"/>

    <Button
        android:id="@+id/btn_get_restful"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送get请求——通过restful拼接网络参数"/>

    <Button
        android:id="@+id/btn_post"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送post请求"/>


LinearLayout>

之后,我们简单用字符串封装一下要请求的URL。这里封装两个URL,是为了演示分别通过传统方式和RestFul风格提交GET请求的不同效果(现在很少有RestFul风格的免费开放api,所以这里就只能假设一个本地的Tomcat服务器,然后放置一个JSON文件来进行校验),代码如下(服务器URL不固定,根据自己的服务器路径名进行相应修改):

	private static final String URL = "https://tcc.taobao.com/cc/json/";

    private static final String LOCALURL = "http://10.0.2.2:8080/";

这里的URL是一个目前还开放的可以查看电话归属地信息的api,而LOCALURL则是本地服务器的api。

另外:保证你的URL路径输入到网页的链接栏中是可以访问的!这点很重要,如果你输入的网页是不存在的(即body为null),那么在调用response.body().string()时就会报出空指针的异常,如图所示:
每天学习一个Android中的常用框架——5.Retrofit_第8张图片

3.5 GET请求——传统网络参数

编写一个名为TestService的接口,其中有一个名为getInfoByHttp的方法,代码如下:

public interface TestService {
/**
     /**
     * 通过拼接网络参数的方式提交GET请求(下面的参数为https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15878896543)
     * 注意:这种方式为http的参数传递方式,若使用这种方式请求,需要在注解上使用@Query而非@Path
     * @param tel
     * @return
     */
    @GET("mobile_tel_segment.htm")
    Call<ResponseBody> getInfoByHttp(@Query("tel") String tel);
}

我们定义了一个getInfoByHttp方法,其返回类型为retrofit的Call类型,尖括号里是okhttp的ResponseBody类型,@GET注解的作用是声明采用GET的方法进行网络请求,而@Query注解的作用是声明其之后的String tel参数,将以路径的形式被拼接到@GET注解括号里的{mobile_tel_segment.htm}处。比如说,之后我们在调用getInfoByHttp方法时传入参数15878896543@GET注解里将会被转化为 mobile_tel_segment.htm?tel=15878896543,这个15878896543又会被接到我们之前设置的baseUrl之后,变成 https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15878896543,这样就变成了一个完整的网络请求地址。

其实使用Retrofit进行GET请求有点类似于OkHttp,步骤可以大抵分为:

  • 通过建造者模式创建Retrofit对象
  • 通过Retrofit对象的create()方法来获取服务接口的实例
  • 通过接口服务的实例来创建Call对象
  • 通过Call对象的enqueue()异步提交请求
  • 通过response.body().string()获取请求信息

代码如下:

private void getByRetrogit() {
        btn_get.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 1.使用建造者模式创建Retrofit实例
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(URL)
                        .build();
                // 2.使用Retrofit对象调用create()创建服务实例(BookService)
                TestService testService = retrofit.create(TestService.class);
                // 3.通过服务实例创建Call对象
                Call<ResponseBody> call = testService.getInfoByHttp("15878896543");
                // 4.通过Call对象构建网络请求(异步)
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            String output = response.body().string();
                            Log.i(TAG,"GET请求发送成功!获取到的信息为:" + output);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Log.i(TAG,"GET请求发送失败");
                    }
                });
            }
        });
    }

测试效果如图所示:
每天学习一个Android中的常用框架——5.Retrofit_第9张图片

3.6 GET请求——RestFul风格

编写一个名为TestService的接口,其中有一个名为getInfoByRestFul的方法,代码如下:

public interface TestService {
/**
     * 通过restful的方式提交GET请求(下面的参数为http://10.0.2.2:8080/update74.json)
     * @param filename
     * @return
     */
    @GET("{filename}")
    Call<ResponseBody> getInfoByRestFul(@Path("filename") String filename);
}

我们定义了一个getInfoByRestFul方法,其返回类型为retrofit的Call类型,尖括号里是okhttp的ResponseBody类型,@GET注解的作用是声明采用GET的方法进行网络请求,而@Path注解的作用是声明其之后的String filename参数,将以路径的形式被替换到@GET注解括号里的{filename}处。比如说,之后我们在调用getInfoByRestFul方法时传入参数update74.json@GET注解里将会被转化为 update74.json,这个update74.json又会被接到我们之前设置的baseUrl之后,变成 http://10.0.2.2:8080/update74.json,这样就变成了一个完整的网络请求地址。

其实使用Retrofit进行GET请求有点类似于OkHttp,步骤可以大抵分为:

  • 通过建造者模式创建Retrofit对象
  • 通过Retrofit对象的create()方法来获取服务接口的实例
  • 通过接口服务的实例来创建Call对象
  • 通过Call对象的enqueue()异步提交请求
  • 通过response.body().string()获取请求信息

代码如下:

private void getByRetrogitForRestful() {
        btn_get_restful.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 1.使用建造者模式创建Retrofit实例
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(LOCALURL)
                        .build();
                // 2.使用Retrofit对象调用create()创建服务实例(BookService)
                TestService testService = retrofit.create(TestService.class);
                // 3.通过服务实例创建Call对象
                Call<ResponseBody> call = testService.getInfoByRestFul("update74.json");
                // 4.通过Call对象构建网络请求(异步)
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            String output = response.body().string();
                            Log.i(TAG,"GET请求发送成功!获取到的信息为:" + output);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Log.i(TAG,"GET请求发送失败");
                    }
                });
            }
        });
    }

测试效果如图所示:
每天学习一个Android中的常用框架——5.Retrofit_第10张图片

3.7 POST请求

编写一个名为TestService的接口,其中有一个名为postInfoByRestFul的方法,代码如下:

public interface TestService {
/**
     * 通过restful的方式提交POST请求(下面的参数为http://10.0.2.2:8080/update74.json)
     * @param filename
     * @return
     */
    @POST("{filename}")
    Call<ResponseBody> postInfoByRestFul(@Path("filename") String filename);
}

事实上,发送POST请求与GET请求的区别就是注解,需要使用@POST。其他的调用方式跟上面是一样的,创建POST请求提交的步骤也是跟GET请求也一样,所以这里就不再赘述了,直接贴上代码:

private void postByRetrogit() {
        btn_post.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 1.使用建造者模式创建Retrofit实例
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(LOCALURL)
                        .build();
                // 2.使用Retrofit对象调用create()创建服务实例(BookService)
                TestService testService = retrofit.create(TestService.class);
                // 3.通过服务实例创建Call对象
                Call<ResponseBody> call = testService.postInfoByRestFul("update74.json");
                // 4.通过Call对象构建网络请求(异步)
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            String output = response.body().string();
                            Log.i(TAG,"POST请求发送成功!获取到的信息为:" + output);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Log.i(TAG,"POST请求发送失败");
                    }
                });
            }
        });
    }

测试效果如图所示:每天学习一个Android中的常用框架——5.Retrofit_第11张图片

4.源码地址

AFL——Android框架学习

你可能感兴趣的:(Android)