码迷,mamicode.com
首页 > 移动开发 > 详细

Android 初识Retrofit

时间:2016-05-12 19:12:05      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:

什么是 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的奉献。

Android 初识Retrofit

标签:

原文地址:http://blog.csdn.net/jdsjlzx/article/details/51354778

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!