Android 网络请求库Retrofit简单使用

什么是 Retrofit ?

Retrofit 是一套 RESTful 架构的 Android(Java) 客户端实现,基于注解,提供 JSON to POJO(Plain Ordinary Java Object ,简单 Java 对象),POJO to JSON,网络请求(POST,GET, PUT,DELETE 等)封装。

既然只是一个网络请求封装库,现在已经有了那么多的大家已经耳熟能详的网络请求封装库了,为什么还要介绍它呢,原因在于 Retrofit 是一套注解形的网络请求封装库,让我们的代码结构更给为清晰。它可以直接解析JSON数据变成JAVA对象,甚至支持回调操作,处理不同的结果。
想更详细的了解 Retrofit,可以查看官方文档

话不多说,直入主题~~

一、集成

目前我使用的是AndroidStudio,那么在model的build.gradle文件中添加以下引用:

compile 'com.squareup.okhttp3:okhttp:3.2.0' 
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'

说明:

Retrofit依赖于okhttp,所以需要集成okhttp
API返回的数据为JSON格式,在此我使用的是Gson对返回数据解析.请使用最新版的Gson

二、返回的数据格式

使用的是百度API的数据接口:名人名言API

QQ截图20160315114933.png
QQ截图20160315115050.png

该接口的API主机地址为:http://apistore.baidu.com
需要访问的接口:avatardata/mingrenmingyan/lookup;

需要一个key等于apikey的Header和一个keyword等于名人名言的查询关键字,而且该请求为GET请求.

访问该API返回的数据格式如下:

{
    "total": 914,
    "result": [
        {
            "famous_name": "布兰登",
            "famous_saying": "人生至善,就是对生活乐观,对工作愉快,对事业兴奋。"
        },
        {
            "famous_name": "魏书生",
            "famous_saying": "抽打自己的鞭子要掌握在自己的手里,在漫长的人生道路的每一步上,都要经常鞭策自警,万不可以为有过一两次抽打就可以沿途平安了。"
        },
        {
            "famous_name": "亨·易卜生",
            "famous_saying": "夺走了普通人生活的幻想,也就等于夺去了他的幸福"
        },
        {
            "famous_name": "佚名",
            "famous_saying": "不知道自己走向何方的人,大都是人生的匆匆过客。"
        },
        {
            "famous_name": "南丁格尔",
            "famous_saying": "人生欲求安全,当有五要。一是清洁空气,二是澄清饮水,三是流通沟渠,四是扫洒屋宇,五是日光充足。"
        }
    ],
    "error_code": 0,
    "reason": "Succes"
}

三、AndroidStudio插件 GsonFormat

我们根据上面API返回的json数据来创建一个FamousInfo数据对象,我们可以利用AndroidStudio插件 GsonFormat 快速,方便的将json数据转为Java 对象,
FamousInfo.java

package com.woyou.androidsample.bean;

import java.util.List;

/**
 * Created by Xiho on 2016/3/14.
 */
public class FamousInfo {

    /**
     * total : 227
     * result : [{"famous_name":"车尔尼雪夫斯基","famous_saying":"非凡的单纯,非凡的明确\u2014\u2014这是天才的智慧的最可惊人的品质。"},{"famous_name":"约·德莱顿","famous_saying":"天才在社会生活中往往显得迟钝而"},{"famous_name":"雨果","famous_saying":"敢于冲撞命运才是天才"},{"famous_name":"卡莱尔","famous_saying":"所谓天才,就是比任何人都先抵挡痛苦的经验本领。"},{"famous_name":"林肯","famous_saying":"卓越的天才不屑走一条人家走过的路。他寻找迄今没有开拓过的地区。"},{"famous_name":"席勒","famous_saying":"产生天才的土壤比天才还要难找"},{"famous_name":"爱因斯坦","famous_saying":"任何天才不能在孤独的状态中发展"},{"famous_name":"民谚","famous_saying":"名人的古怪行为是天才的标志,凡人的古怪行为是神经出了毛病"},{"famous_name":"鲁迅","famous_saying":"哪里有天才,我是把别人喝咖啡的工夫都用在了工作上了。"},{"famous_name":"塞涅夫","famous_saying":"没有某些发狂的劲头,就没有天才。"},{"famous_name":"狄德罗","famous_saying":"精神的浩瀚想象的活跃心灵的勤奋:就是天才。"},{"famous_name":"爱默生","famous_saying":"平凡的人希望,天才的人创造。"},{"famous_name":"契诃夫","famous_saying":"真正的天才是常常隐藏在群众里面,绝不挤向人前去露脸的。"},{"famous_name":"别林斯基","famous_saying":"任何天才,不经过艰苦不断的劳动,不经过最使空想家头疼和懊恼的最初纯物质和机械的劳动,就无法精通任何种类的艺术。"},{"famous_name":"杨格","famous_saying":"我愿意以天才比美德,以学问比财富。如美德越少的人,越需要财富,天才越低的人,越需要学问。"},{"famous_name":"巴尔扎克","famous_saying":"职业尽管不同,但天才的品德并无分别。"},{"famous_name":"恩格斯","famous_saying":"逆境使天才脱颖而出,顺境会埋没"},{"famous_name":"巴尔扎克","famous_saying":"破坏的人和建设的人,两者都是意志的现象:一个是准备工作,另一个是完成工作;前者好像是一个恶的天才,后者似乎是一个善的天才;对这一个给予光荣,对另一个给予忘却。恶者哇啦哇啦,把庸俗的人们从梦里惊醒,对他佩服得五体投地,可是善者却一直默不作声。"},{"famous_name":"培根","famous_saying":"如果孩子确有某种超群的天才,那当然应该扶植发展。但就一般情况说,下面这句格言很有用的:\u201c长期的训练会通过适应化难为易。\u201d"},{"famous_name":"爱迪生","famous_saying":"天才是百分之一的灵感,百分之九十九的血汗。"}]
     * error_code : 0
     * reason : Succes
     */

    private int total;
    private int error_code;
    private String reason;
    /**
     * famous_name : 车尔尼雪夫斯基
     * famous_saying : 非凡的单纯,非凡的明确——这是天才的智慧的最可惊人的品质。
     */

    private List<ResultEntity> result;

    public void setTotal(int total) {
        this.total = total;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public void setResult(List<ResultEntity> result) {
        this.result = result;
    }

    public int getTotal() {
        return total;
    }

    public int getError_code() {
        return error_code;
    }

    public String getReason() {
        return reason;
    }

    public List<ResultEntity> getResult() {
        return result;
    }

    public static class ResultEntity {
        private String famous_name;
        private String famous_saying;

        public void setFamous_name(String famous_name) {
            this.famous_name = famous_name;
        }

        public void setFamous_saying(String famous_saying) {
            this.famous_saying = famous_saying;
        }

        public String getFamous_name() {
            return famous_name;
        }

        public String getFamous_saying() {
            return famous_saying;
        }
    }
}


四、实现过程

首先, 按照官方的说明,我们需要创建一个接口,返回 Call<FamousInfo>;如下:

@GET("/avatardata/mingrenmingyan/lookup")
    Call<FamousInfo> getFamousResult(@Header("apiKey") String apiKey,
                                     @Query("keyword") String keyword,
                                     @Query("page") int page,
                                     @Query("rows") int rows);

这里我们使用的是Retrofit 提供注解的方式来定义接口的

  • @get后面我们填写需要访问对应的接口地址
  • @Header用来添加Header
  • @Query用来添加查询关键字

现在接口定义好了,我们来** 定义Retrofit 网络接口服务的包装类 **:

package com.woyou.androidsample;

import android.content.Context;

import retrofit2.GsonConverterFactory;
import retrofit2.Retrofit;

/**
 * Retrofit 网络接口服务的包装类
 * Created by Xiho on 2016/3/14.
 */
public class RetrofitWrapper {
    private static RetrofitWrapper instance;
    private Context mContext;
    private Retrofit retrofit;

    private RetrofitWrapper() {
           //1.创建Retrofit对象
        retrofit = new Retrofit.Builder().baseUrl(Constant.BASEURL) // 定义访问的主机地址
                .addConverterFactory(GsonConverterFactory.create())  //解析方法
                .build();
    }
    /**
     * 单例模式
     *
     * @return
     */
    public static RetrofitWrapper getInstance() {
        if (instance == null) {
            synchronized (RetrofitWrapper.class){
                if (instance==null){
                    instance = new RetrofitWrapper();
                }
            }
        }
        return instance;
    }


    public <T> T create(final Class<T> service) {
        return retrofit.create(service);
    }

}



/** 
   * Created by Xiho on 2016/3/14. 
   */
public class Constant {    
    public  static String BASEURL="http://apis.baidu.com"; //服务器地址   
    public  static String APIKEY="4c4f0c3c49e09d5578ae0ba49fa84a97";

}

网络服务的包装类定义好了之后,在定义一个访问的Model(个人编码风格,其实可以更简洁点)。

public class FamousInfoModel {
    private static FamousInfoModel famousInfoModel;
    private FamousService mFamousService;

    /**
     * 单例模式
     *
     * @return
     */
    public static FamousInfoModel getInstance(Context context) {
        if (famousInfoModel == null) {
            famousInfoModel = new FamousInfoModel(context);
        }
        return famousInfoModel;
    }


    private FamousInfoModel(Context context) {
        mFamousService = (FamousService) RetrofitWrapper.getInstance().create(FamousService.class);
    }

    /**
     * 查询名人名言
     *
     * @param famousInfoReq
     * @return
     */
    public Call<FamousInfo> queryLookUp(FamousInfoReq famousInfoReq) {
        Call<FamousInfo> infoCall = mFamousService.getFamousResult(famousInfoReq.apiKey, famousInfoReq.keyword, famousInfoReq.page, famousInfoReq.rows);
        return infoCall;
    }
}

五、如何使用

构建好接口以后,可以使用了!

使用分为四步:

  • 创建Retrofit对象
  • 创建访问API的请求
  • 发送请求
  • 处理结果
    主要代码如下:
FamousInfoModel famousInfoModel =FamousInfoModel.getInstance(getApplicationContext());
// 获取事件
    private void initEvent() {
        mSerachBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //创建访问的API请求
                Call<FamousInfo> callFamous= famousInfoModel.queryLookUp(initParams());
                //发送请求
                callFamous.enqueue(new Callback<FamousInfo>() {
                    @Override
                    public void onResponse(Call<FamousInfo> call, Response<FamousInfo> response) {
                        if(response.isSuccess()){
                            FamousInfo result = response.body();
                            if(result!=null){
                                List<FamousInfo.ResultEntity> entity = result.getResult();
                                    mTxtContent.setText("1、"+entity.get(0).getFamous_saying()+"\n---"+entity.get(0).getFamous_name()+"\n 2、"
                                            +entity.get(1).getFamous_saying()+"\n---"+entity.get(1).getFamous_name());
                            }
                        }
                    }
                    @Override
                    public void onFailure(Call<FamousInfo> call, Throwable t) {

                    }
                });
            }
        });
    }

最后运行的效果图如下:

QQ截图20160315124740.png
QQ截图20160315124757.png

** 搜索的结果我只是显示了其中一部分,只用来使用Retrofit 这个框架,没有很具体去做一些处理啦,后面还会用一些其他的库,还会使用本Demo 来进行测试,所以这次就简单写了下。** <br />
附上源码:AndroidRetrofitSample <br />

六、扩展阅读

** Retrofit:**

我的博客:http://blog.csdn.net/u011974987

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,424评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 浑浑噩噩过了两周,有喜悦,有痛苦,就像众多生活一样,快乐且悲伤,我发现我迫不及待喜欢上现在住的地方,走半小时到国图...
    大鹏_29wp阅读 177评论 0 2
  • 批判性思维 延伸:独立思考能力 最值钱的批判性思维能力,大概有五种。 1)探索新事...
    雾欣雨鲜阅读 342评论 0 3
  • 苦逼的日子即将来临,我会不会瘦那么个几斤呢~出去工作还省的被催,毕竟我感觉自己还是要去赚奶粉钱~哈哈哈
    静守时光mxx阅读 299评论 0 0