Android 初识Retrofit

什么是 Retrofit ?

Retrofit 是一套 RESTful 架构的 AndroidJava
客户端实现,基于注解,提供 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

该接口的API主机地址为:http://apistore.baidu.com

需要访问的接口:avatardata/mingrenmingyan/lookup;

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

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

{
    "total": 227,
    "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.baidu.retrofit.bean;

import java.util.List;

public class FamousInfo {
    /*{
        "total": 227,
            "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"
    }*/

    //下面变量的定义要与接口中的字段名字保持一致
    private int total;
    private int error_code;
    private String reason;
    private List<ResultEntity> 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;
        }
    }

    public int getTotal() {
        return total;
    }

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

    public int getError_code() {
        return error_code;
    }

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

    public String getReason() {
        return reason;
    }

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

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

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

四、实现过程

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

package com.baidu.retrofit.intf;

import com.baidu.retrofit.bean.FamousInfo;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Query;

/**
 * Created by lizhixian on 16/5/8.
 */
public interface IFamousInfo {

    @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.baidu.retrofit;

import android.content.Context;

import retrofit2.GsonConverterFactory;
import retrofit2.Retrofit;

/**
 * Created by lizhixian on 16/5/8.
 */
public class RetrofitWrapper {
    private static RetrofitWrapper instance;
    private Context mContext;
    private Retrofit mRetrofit;

    public RetrofitWrapper() {
        mRetrofit = new Retrofit.Builder().baseUrl(Constant.BASEURL)
                .addConverterFactory(GsonConverterFactory.create()).build();
    }

    public  static RetrofitWrapper getInstance(){

        if(null == instance){
            synchronized (RetrofitWrapper.class){
                instance = new RetrofitWrapper();
            }
        }
        return instance;
    }

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

网络服务的包装类定义好了之后,在定义一个访问的Model。

package com.baidu.retrofit.model;

import android.content.Context;

import com.baidu.retrofit.RetrofitWrapper;
import com.baidu.retrofit.bean.FamousInfo;
import com.baidu.retrofit.bean.FamousInfoReq;
import com.baidu.retrofit.intf.IFamousInfo;

import retrofit2.Call;

/**
 * Created by lizhixian on 16/5/8.
 */
public class FamousInfoModel {
    private static FamousInfoModel famousInfoModel;
    private IFamousInfo mIFamousInfo;

    public FamousInfoModel(Context context) {
        mIFamousInfo = RetrofitWrapper.getInstance().create(IFamousInfo.class);
    }

    public static FamousInfoModel getInstance(Context context){
        if(famousInfoModel == null) {
            famousInfoModel = new FamousInfoModel(context);
        }
        return famousInfoModel;
    }

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

五、如何使用

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

使用分为四步:

  • 创建Retrofit对象
  • 创建访问API的请求
  • 发送请求
  • 处理结果 

    主要代码如下:

package com.baidu.retrofit;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.baidu.retrofit.bean.FamousInfo;
import com.baidu.retrofit.bean.FamousInfoReq;
import com.baidu.retrofit.model.FamousInfoModel;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    public final String TAG= this.getClass().getName();
    private FamousInfoModel famousInfoModel;

    @BindView(R.id.edit_keyword)
    EditText mEditKeyWord;
    @BindView(R.id.button_search)
    Button mSerachBtn;
    @BindView(R.id.txt_content)
    TextView mTxtContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initView();

        famousInfoModel = FamousInfoModel.getInstance(this);
    }

    /**
     * 初始化View
     */
    private void initView() {

    }

    @Override
    @OnClick({ R.id.button_search })
    public void onClick(View view) {

        Log.d(TAG,"onclick");
        if(view.getId() == R.id.button_search) {

            famousInfoModel.queryLookUp(initParams()).enqueue(new Callback<FamousInfo>() {
                @Override
                public void onResponse(Call<FamousInfo> call, Response<FamousInfo> response) {

                    if(response.isSuccess()) {
                        FamousInfo result = response.body();
                        if(null != result) {
                            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) {

                }
            });
        }
    }

    private FamousInfoReq initParams() {
        FamousInfoReq mFamousInfoReq = null;
        mFamousInfoReq= new FamousInfoReq();
        mFamousInfoReq.apiKey= Constant.APIKEY;
        mFamousInfoReq.keyword = mEditKeyWord.getText().toString();
        mFamousInfoReq.page=1;
        mFamousInfoReq.rows=20;
        return  mFamousInfoReq;

    }
}

效果图:

附上源码:https://github.com/jdsjlzx/RetrofitDemo

本文参考并借鉴了博客:http://blog.csdn.net/u011974987/article/details/50895633

如果不想使用注解,请到上面博客下载代码。

最后感谢_xuhao的奉献。

时间: 2024-10-21 21:58:22

Android 初识Retrofit的相关文章

Android初识之Activity组件

之前自己的编程完全是在PC上进行的,而且主要是在算法和数据结构上.由于某些需要加之认识到Android的重要性,且大学走到现在基本上没什么课了,空闲时间很多,于是就开始学习Android.本系列博客都将围绕Android应用程序设计展开,由于本人是完全没有Android程序设计基础,所以内容都很基础,希望与大家交流学习并得到指点. 1.Activity类的onCreate()方法 对于具有可视化界面的Android程序来说,必然要有一个Activity类或其派生类对象.一般来说,Activity

Android使用Retrofit技术仿微信图片上传,可以选择多张图片拍照上传

Android 仿照微信发说说,既能实现拍照,选图库,多图案上传 使用Retrofit技术. 使用方法:详见博客 http://blog.csdn.net/u010046908/article/details/50767904 项目的运行效果: 服务器端接收文件的action UploadFile.java @Controller public class UploadFile extends ActionSupport { /** * */ private static final long

Android开发 retrofit入门讲解

前言 retrofit基于okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.如果你不了解OKhttp建议你还是先了解它在来学习使用retrofit,传送门:Android 开发 框架系列 OkHttp使用详解 Retrofit优势,就是简洁易用,解耦,扩展性强,可搭配多种Json解析框架(例如Gson),另外还支持RxJava.但是,这篇博客不讲解RxJava配合使用的部分,与RxJava的配合使用将在另外一篇博客中讲解.

Android初识

最近大学最好的兄弟再次考研失利了,没有办法只能先出来工作了,由于他非常喜欢android,所以就在自己学习android了,但是由于他之前没有什么开发经验,所以学起来还是挺困难的,因此我就决定帮他一把.毕竟我自己也做iOS开发一年多了,所以相信学起android起来也不是很费力的,这样可以把他领进门的.下面就开始我的android学习之旅了,写的不好的地方多包涵(这里还得非常感谢我的android同事,好多不懂的都得请教他) 首先安装开发工具,建议直接安装一个android adt既可,里面包含

Android初识Media类的EXTERNAL_CONTENT_URI和INTERNAL_CONTENT_URI

今天有个客户需求,要内置一个不可删除的视频. 不可删除的话,不能在设备中删除,USB连接电脑也不能删除.那么直接放到system/media/下好了,这样对用户就完全不可见了,这样还不行,完全不可见,就失去了内置视频的意义,所以我们还要在视频播放器中显示出来,这就要修改播放器的源码,让播放器读取Internal的媒体文件即可. adb shell,查看如下目录 /data/data/com.android.providers.media/databases/ 可以看到有两个数据库文件:exter

Android 使用retrofit时,怎样获取响应的头信息

这个问题,我前段时间在项目中使用Retrofit遇到过,最后查到的解决办法有两种获取Response Headers的方法,第一种是直接在定义接口是让接口返回Retrofit的Response对象,在Response对象中可以获取到Headers,如: @GET("/****act=****") Response<SomeClass> getSomeData(); 在操作Response对象时,使用response.headers():得到Headers. 这样做需要修改所

Android使用Retrofit请求WebService

1.配置app build.gradle /** * network */ compile 'com.squareup.retrofit2:retrofit:2.0.2' compile('com.squareup.retrofit2:converter-simplexml:2.0.2') { exclude group: 'stax', module: 'stax-api' exclude group: 'stax', module: 'stax' exclude group: 'xpp3',

Android——初识RxJava

最近在看RxJava,在这里分享一下自己看的一些介绍RxJava不错的文章. 这是RxJava和RxAndroid在Github上的链接: RxJava Github主页:RxJava Github主页 RxAndroid Github主页:RxAndroid Github主页 下面是大头鬼Bruce对RxJava介绍的译文: 1.深入浅出RxJava(一:基础篇) 2.深入浅出RxJava(二:操作符) 3.深入浅出RxJava三–响应式的好处 4.深入浅出RxJava四-在Android中使

Android 初识Activity1

Activity是android的四大组件之一,也是最重要的负责跟用户进行界面交互的组件.当然,现在也有人把Intent(意图)放到里面,称为android五大组件. 这个问题上,Summer认为是个仁者见仁智者见智的问题,这里不进行辩驳. 在android的开发中,很多地方要使用到activity类所定义的方法,常用到的如下: 上面只是总结了几个在activity中设置组件常用到的方法,Activity类还提供了Menu.Service.Intent等操作支持,暂时不列举,以后复习到 的时候会