Retrofit网络框架入门使用

Stella981
• 阅读 910

1.简单介绍

retrofit事实上就是对okhttp做了进一步一层封装优化。

我们仅仅须要通过简单的配置就能使用retrofit来进行网络请求了。

Retrofit能够直接返回Bean对象,比如假设我们进行一个网络接口的请求。返回来一串json字符串。那么这个时候一般我们都要拿到这个json字符串后进行解析得到相应的Bean对象,Retrofit仅仅要依赖一下Gson的转换库然后进行简单的配置就能够直接拿到Bean对象了,不须要我们自己去解析。

接触过OKHttp的人会发现,Retrofit和OKHttp的代码有些地方有很大的类似度。

他的性能很的棒,国外大牛(被墙了)已经做过測例如以下图:

Retrofit网络框架入门使用

看了这个图之后你有什么想法?

Talk is cheap, show me the code!

2.高速使用

在实际项目开发中get、post请求使用居多。那我们以get请求来做个入门小案例。

http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8

以上连接是一个get请求方式。參数在地址后面使用“?”进行名值对的拼接。请求的结果是一个json字符串数据。例如以下

{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.8.8.8"}}

来个简单的Demo界面例如以下:
功能很easy,一个输入框输入IP地址,然后获取IP地址所在的国家。

Retrofit网络框架入门使用

1)环境的配置

如今预计很少人用eclipse做项目开发了。eclipse的方式就不另赘述了(GitHub上也是有jar依赖下载的)。我们这里的开发工具是用的Android Studio,在 GitHub项目地址:https://github.com/square/retrofit能够找到Gradle的依赖代码:
加入两个依赖:retrofit依赖。和gson转换器。

compile 'com.squareup.retrofit2:retrofit:2.1.0'//眼下最新的版本号
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//加入好这个依赖后我们就能够进行数据转换器的配置了。retrofit内部就会帮我们去转换json字符串为Java对象

在AS里面的效果例如以下:
Retrofit网络框架入门使用

converter-gson依赖的版本号号与retrofit依赖版本号号保持一致。我们在GitHub上能够看到。他们在同一个project里面的。

2)代码

布局很easy就不另贴代码了。类也不多參看以下的包结构图
Retrofit网络框架入门使用

Retrofit操作步骤

① 先把接口返回来的数据bean对象写好。

能够直接使用工具转化。如GsonFormat工具

public class IpInfo {
    public int code;
    public DataBean data;

    public static class DataBean {
        public String country;
        public String country_id;
        public String area;
        public String area_id;
        public String region;
        public String region_id;
        public String city;
        public String city_id;
        public String county;
        public String county_id;
        public String isp;
        public String isp_id;
        public String ip;

    }

}
② 定义API接口

一般来讲都是处理遵循RESTful接口规范的http接口,我们须要把接口转化为Java Interface。

/**
 * 这个接口就是普通的借口类,可是看到里面的方法来,会有一些注解定义相关的功能
 * 如@GET定义请求方式为get请求方式,假设有參数能够使用@Query、@QueryMap定义
 */

public interface IpService {
    /**
     * @return 固定返回值为Call。当中泛型指定是进行请求后返回终于得数据类型。
③ 初始化Retrofit,创建接口实例,进行异步请求

代码凝视灰常仔细了

/**
 *Retrofit简单有用案例
 *
 * 採用http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.2 地址进行查询
 */
public class MainActivity extends AppCompatActivity {

    public static final String baseUrl = "http://ip.taobao.com/service/";
    private TextView tvResult;
    private EditText etIp;

    IpService ipService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvResult = (TextView) findViewById(R.id.tv_result);
        etIp = (EditText) findViewById(R.id.et_ip);

        initRetrofit();
    }

     /**
     * 初始化Retrofit实例。并创建接口类。
     * 注意:IpService不须要我们去实现。直接Retrofit=类有create方法生成。
     */
    private void initRetrofit() {

        //创建Retrofit的实例,把Gson转换器设置下
        Retrofit retrofit = new Retrofit
                .Builder()
                .baseUrl(baseUrl)//设置API的基础地址
                .addConverterFactory(GsonConverterFactory.create())//设置后才才支持json字符串转化为Bean
                .build();

        //使用Retrofit的create方法传入创建接口实例
        ipService = retrofit.create(IpService.class);
    }

    /**
     * 布局中查询button配置的点击事件
     * @param view
     */
    public void check(View view) {

        String ip = etIp.getText().toString();
        if (TextUtils.isEmpty(ip)) {
            Toast.makeText(this, "ip 不能为空", Toast.LENGTH_SHORT).show();
            return;
        }

        //调用接口声明的方法
        Call<IpInfo> ipInfoCall = ipService.getIpInfo(ip);

        //call能够直接调用异步方法。进行结果获取。须要传入接口回调Callback,
        ipInfoCall.enqueue(new Callback<IpInfo>() {
            @Override
            public void onResponse(Call<IpInfo> call, Response<IpInfo> response) {
                //推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。否则连接失败
                if (response.isSuccessful()) {
                    //直接拿到JavaBean
                    IpInfo ipInfo = response.body();

                    //这里直接能够进行UI操作。OKHttp是不行的哦
                    tvResult.setText(ipInfo.getData().getCountry());

                } else {
                    //请求失败。

3.经常使用注解

GET:get 请求方式
POST:post请求方式
Query:定义get请求參数
QueryMap:定义get请求參数
Field:定义post请求參数
FieldMap:定义post请求參数
Header:定义头參数
HeaderMap:定义头參数
Headers:定义头參数
Path:动态路径
来看看代码是怎么实现的:

public interface SampleApi {

//----------------------GET 请求方式 start --------------------------------
    /**
     * 注解:GET。QUERY,QUERYMAP 的使用
     */

    /**
     * get 请求固定參数形式
     *
     * @return
     */
    @GET("demo?username=zhanghsan&password=123455")
    Call<SampleResponse> getFun();

    /**
     * 使用@Query注解进行參数传递
     *
     * @param username
     * @param password
     * @return
     */
    @GET("demo")
    Call<SampleResponse> getFun(@Query("username") String username, @Query("password") String password);

    /**
     * 使用@QueryMap注解 Map集合进行參数传递
     *
     * @param params
     * @return
     */
    @GET("demo")
    Call<SampleResponse> getFun(@QueryMap Map<String, Object> params);


//----------------------GET 请求方式 end --------------------------------


//----------------------POST 请求方式 start --------------------------------
    /**
     * POST,Field,FieldMap,FormUrlEncoded(POST 方式请求有參数的时候一定不要忘记了这个注解)
     */

    /**
     * post使用@Query注解进行參数传递
     *
     * @param username
     * @param password
     * @return
     */
    @FormUrlEncoded
    @POST("demo")
    Call<SampleResponse> postFun(@Field("username") String username, @Field("password") String password);

    /**
     * POST使用@FiledMap Map集合进行參数传递
     *
     * @param params
     * @return
     */
    @FormUrlEncoded
    @POST("demo")
    Call<SampleResponse> postFun(@FieldMap Map<String, Object> params);


//----------------------POST 请求方式 end --------------------------------

//----------------------head參数加入start --------------------------------

    /**
     * Headers。Header,HeaderMap
     * */

    /**
     * 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下
     *
     * @param username
     * @param password
     * @return
     */
    @Headers(
            {"os:Android"
                    , "osversion:5.0"
            })
    @FormUrlEncoded
    @POST("demo")
    Call<SampleResponse> postFunWithHead(@Field("username") String username, @Field("password") String password);

    /**
     * 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下
     *
     * @param username
     * @param password
     * @return
     */
    @FormUrlEncoded
    @POST("demo")
    Call<SampleResponse> postFunWithHead(@Header("os") String os, @Header("osversion") String osversion, @Field("username") String username, @Field("password") String password);

    /**
     * 有些接口须要传送一些操作client系统的信息,比方系统类型,系统版本号等例如以下
     *
     * @param headParams head 參数。键值对的形式存储到map集合中去
     * @param username
     * @param password
     * @return
     */
    @FormUrlEncoded
    @POST("demo")
    Call<SampleResponse> postFunWithHead(@HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password);

//----------------------head參数加入end --------------------------------

//----------------------path 注解 --------------------------------

    /**
     *  Path注解使用时在请求方式注解后面的URL设置一个占位符,使用大括号包裹。

Activity代码

public class SampleActivity extends AppCompatActivity {
    EditText etName;
    EditText etPassword;
    TextView tvResult;
    SampleApi sampleApi;
    SampleCallBack callback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        etName = (EditText) findViewById(R.id.et_name);
        etPassword = (EditText) findViewById(R.id.et_password);
        tvResult = (TextView) findViewById(R.id.tv_result);

        //使用链式调用建立
        sampleApi = new Retrofit
                .Builder()
                .baseUrl("http://10.0.2.2:8080/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(SampleApi.class);

        callback = new SampleCallBack();


    }


    /**
     * button点击事件
     *
     * @param view
     */
    public void submit(View view) {
        tvResult.setText("正在请求....");

        String name = etName.getText().toString();
        String password = etPassword.getText().toString();

        if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
            Toast.makeText(this, "參数不能为空", Toast.LENGTH_SHORT).show();
            return;
        }
        Call<SampleResponse> call;
        switch (view.getId()) {
            case R.id.btn_get:
                call = sampleApi.getFun(name, password);
                call.enqueue(callback);
                break;
            case R.id.btn_post:
                call = sampleApi.postFun(name, password);
                call.enqueue(callback);
                break;
            case R.id.btn_head:
//                call = sampleApi.postFunWithHead(name, password);//第一种,直接静态定义方式。看接口方法
//                call = sampleApi.postFunWithHead("ios","10.10.10",name, password);//另外一种,能够动态配置值得方式
                Map<String, String> map = new HashMap<>();
                map.put("os", "android");
                map.put("osversion", "9.9.9999999");
//                call = sampleApi.postFunWithHead(map, name, password);//第三种,能够动态配置參数和值得形式
                call = sampleApi.postFunWithHead("demo",map, name, password);//第四种,结合Path定义路径
                call.enqueue(callback);
                break;
        }
    }


    /**
     * @param result
     * 显示结果
     */
    public void showResult(String result) {
        tvResult.setText(result);
    }


    /**
     * 回调实现类
     */
    public class SampleCallBack implements Callback<SampleResponse> {
        @Override
        public void onResponse(Call<SampleResponse> call, Response<SampleResponse> response) {
            //推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。否则连接失败
            if (response.isSuccessful()) {
                //直接拿到JavaBean
                SampleResponse sampleResponse = response.body();

                //这里直接能够进行UI操作。OKHttp是不行的哦
                showResult(sampleResponse.toString());

            } else {
                //请求失败。

执行效果

Retrofit网络框架入门使用

4.URL操作注意事项

拼接注意,建议baseUrl用“/”结尾。接口中请求方式后面的url不用”/”开头

样例:baseUrl=http://10.0.2.2:8080/market/ url=home

错误案例

案例一:
baseUrl=http://10.0.2.2:8080/market url=home
—>http://10.0.2.2:8080/home
分析:默认用最后一个斜线去拼接

案例二:
baseUrl=http://10.0.2.2:8080/market url=/home
—>http://10.0.2.2:8080/home
分析:url中開始的斜线代表主机地址http://10.0.2.2:8080

源码下载

Retrofit还能够实现上传下载以及 结合RxJava使用,等下回分解!

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
4个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
浅梦一笑 浅梦一笑
4个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
4个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
4个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Easter79 Easter79
1年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue