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