Retrofit 2.0 + OkHttp 3.0+JSON网络请求
来源:互联网 发布:数据交易是指什么 编辑:程序博客网 时间:2024/06/06 18:34
Retrofit 和 OkHttp 都是伟大的 Square 公司开源的伟大项目。我从 2014 年便在同事 ionull 的推荐带领下,使用这个网络库组合以及 RxJava,真是极大改善 Android 开发体验的好东西。前段时间也是从 Retrofit 1.9 升级到 2.0 beta 4 版本,从 OkHttp 2.+ 版本升级到 3.0.1 版本。这两者在各自的这两个大版本升级中,都改变了不少,使得原本的代码都需要进行一些修改才能使用,我也是稍微摸索了几下,如今大致摸清,把一些基础配置,比如设置 Json 转换器、Rx Java 适配器、设置 Debug Log 模式、设置超时、错误重连,以及配置 Access token Interceptor 等等一些内容,分享一下。
引入依赖:
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'compile 'com.squareup.okhttp3:okhttp:3.0.1'compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
先说 OkHttp 3.0 的配置,3.0 使用层面上的主要改变是,由原本的 okHttp 对象直接各种 set 进行配置改为 Builder 配置模式,所以原本对应的方法应该到 OkHttpClient.Builder 类对象下寻找。我的一些常用配置如下:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(interceptor) .retryOnConnectionFailure(true) .connectTimeout(15, TimeUnit.SECONDS) .addNetworkInterceptor(mTokenInterceptor) .build();
解释:
HttpLoggingInterceptor 是一个拦截器,用于输出网络请求和结果的 Log,可以配置 level 为 BASIC / HEADERS / BODY,都很好理解,对应的是原来 retrofit 的 set log level 方法,现在 retrofit 已经没有这个方法了,所以只能到 OkHttp 这边来配置,并且 BODY 对应原来到 FULL.
retryOnConnectionFailure 方法为设置出现错误进行重新连接。
connectTimeout 设置超时时间
addNetworkInterceptor 让所有网络请求都附上你的拦截器,我这里设置了一个 token 拦截器,就是在所有网络请求的 header 加上 token 参数,下面会稍微讲一下这个内容。
让所有网络请求都附上你的拦截器:
Interceptor mTokenInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); if (Your.sToken == null || alreadyHasAuthorizationHeader(originalRequest)) { return chain.proceed(originalRequest); } Request authorised = originalRequest.newBuilder() .header("Authorization", Your.sToken) .build(); return chain.proceed(authorised); }};
解释:
那个 if 判断意思是,如果你的 token 是空的,就是还没有请求到 token,比如对于登陆请求,是没有 token 的,只有等到登陆之后才有 token,这时候就不进行附着上 token。另外,如果你的请求中已经带有验证 header 了,比如你手动设置了一个另外的 token,那么也不需要再附着这一个 token.
header 的 key 通常是 Authorization,如果你的不是这个,可以修改。
如果你需要在遇到诸如 401 Not Authorised 的时候进行刷新 token,可以使用 Authenticator,这是一个专门设计用于当验证出现错误的时候,进行询问获取处理的拦截器:
Authenticator mAuthenticator = new Authenticator() { @Override public Request authenticate(Route route, Response response) throws IOException { Your.sToken = service.refreshToken(); return response.request().newBuilder() .addHeader("Authorization", newAccessToken) .build(); }}
然后,对于以上的两个拦截器,分别使用 OkHttpClient.Builder 对象的 addNetworkInterceptor(mTokenInterceptor) 和 authenticator(mAuthenticator) 即可。
Retrofit:
对于 Retrofit,我的配置是:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(AppConfig.BASE_URL) .client(client) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .build();service = retrofit.create(YourApi.class);
解释:
baseUrl: 原来的 setEndPoint 方法变成了 baseUrl
client 即上面的 OkHttp3 对象
addCallAdapterFactory 增加 RxJava 适配器
addConverterFactory 增加 Gson 转换器
具体实现一个Demo
利用 Retrofit2.0和okhttp+Json解析百度名人名言:
http://apistore.baidu.com/apiworks/servicedetail/1756.html
1.分四个步骤
1.创建Retrofit对象
2. 创建访问API的请求
3 .发送请求
4.处理结果
首先解决JAR包的问题
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.0' 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' compile 'com.android.support:support-annotations:23.1.1' compile 'com.android.support:design:23.1.0'}
还有配置文件
<uses-permission android:name="android.permission.INTERNET" />
根据官方文档我们需要创建一个接口,并且选择请求方式,返回一个Call对象/** * Created by gaomin on 2016/4/14. */public interface FamousService { @GET("avatardata/mingrenmingyan/lookup") Call<FamousInfo>getFamousResult(@Header("apiKey") String apiKey , //请求秘钥参数 @Query("keyword") String keyword ,//请求关键字 @Query("page") String page, //请求页数 @Query("rows") String rows); //请求记录条数} 现在接口定义好了,我们来* 定义Retrofit 网络接口服务的包装类 *: /** * Created by gaomin on 2016/4/14. * 网络接口包装类建议使用单例模式 * 并且可以使用双重加锁代码块,避免多线程和效率 */public class RetrofitWrapper { private static volatile RetrofitWrapper sInstance; private Retrofit retrofit; private RetrofitWrapper(){ retrofit = new Retrofit.Builder() .baseUrl(GMUrl.BASEURL) //访问主机地址 .addConverterFactory(GsonConverterFactory.create()) //解析方式 .build(); } public static RetrofitWrapper getInstance(){ if(null == sInstance){ synchronized (RetrofitWrapper.class){ if(null == sInstance){ sInstance = new RetrofitWrapper(); } } } return sInstance; }; public <T> T create(final Class<T> service){ return retrofit.create(service); }} 网络服务的包装类定义好了之后,在定义一个访问的Modelpackage com.gaomin.retrofitokhttpdemo.Model;import com.gaomin.retrofitokhttpdemo.RetrofitWrapper;import com.gaomin.retrofitokhttpdemo.bean.FamousInfo;import com.gaomin.retrofitokhttpdemo.bean.FamousInfoReq;import com.gaomin.retrofitokhttpdemo.serviceAPi.FamousService;import retrofit2.Call;/** * Created by gaomin on 2016/4/14. * 这里采用懒汉式单例模式 * 不考虑多线程方面问题 */public class FamousInfoModel { private static FamousInfoModel sInstance; private FamousService mFamousService; public static FamousInfoModel getInstance(){ if(null == sInstance){ sInstance = new FamousInfoModel(); } return sInstance; } private FamousInfoModel(){ 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; }}构建好接口以后,可以使用了!package com.gaomin.retrofitokhttpdemo;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.EditText;import android.widget.ImageButton;import android.widget.ListView;import android.widget.TextView;import com.gaomin.retrofitokhttpdemo.Model.FamousInfoModel;import com.gaomin.retrofitokhttpdemo.bean.FamousInfo;import com.gaomin.retrofitokhttpdemo.bean.FamousInfoReq;import java.util.ArrayList;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;public class MainActivity extends AppCompatActivity { ArrayList<FamousInfo.ResultEntity> entity; private ListView mListView; public final String TAG=this.getClass().getName(); private FamousInfoModel famousInfoModel; private EditText mEditKeyWord; private ImageButton mSerachBtn; private TextView mTxtContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); famousInfoModel =FamousInfoModel.getInstance(); entity = new ArrayList<FamousInfo.ResultEntity>(); initView(); initParams(); initEvent(); } /** * 初始化View */ private void initView() { mEditKeyWord = (EditText) findViewById(R.id.edit_keyword); mSerachBtn = (ImageButton) findViewById(R.id.button_search); mListView = (ListView)findViewById(R.id.mListView); } /** * 初始化参数 */ private FamousInfoReq initParams() { FamousInfoReq mFamousInfoReq=null; mFamousInfoReq= new FamousInfoReq(); mFamousInfoReq.apiKey= GMUrl.APIKEY; mFamousInfoReq.keyword =mEditKeyWord.getText().toString(); mFamousInfoReq.page=3; mFamousInfoReq.rows=30; return mFamousInfoReq; } // 获取事件 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){ entity = (ArrayList<FamousInfo.ResultEntity>) result.getResult(); mListView.setAdapter(new MyAdapter(entity)); } } } @Override public void onFailure(Call<FamousInfo> call, Throwable t) { } }); } }); } class MyAdapter extends BaseAdapter{ private ArrayList entityBAArrayList; public MyAdapter(ArrayList a){ entityBAArrayList = a; } @Override public int getCount() { return entityBAArrayList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder =null; if(null == convertView){ viewHolder = new ViewHolder(); convertView = getLayoutInflater().inflate(R.layout.listview_item,null); viewHolder.titleTV = (TextView)convertView.findViewById(R.id.titleTV); viewHolder.contentTV = (TextView)convertView.findViewById(R.id.contentTV); convertView.setTag(viewHolder); }else { viewHolder = (ViewHolder)convertView.getTag(); } viewHolder.titleTV.setText("名人--"+entity.get(position).getFamous_name()); viewHolder.contentTV.setText(entity.get(position).getFamous_saying()); return convertView; } } class ViewHolder{ private TextView titleTV; private TextView contentTV; }}javabean对象就不给出来了,自己看具体的JSON写吧,或者用工具解析
- Retrofit 2.0 + OkHttp 3.0+JSON网络请求
- Retrofit+okhttp网络框架请求
- Android网络请求XUtils、Volley、OkHttp、Retrofit
- 网络请求框架 Rxjava+ReTrofit+okHttp+MVP
- Android使用Retrofit+OkHttp实现网络请求
- rxjava+Retrofit+okhttp 实战网络请求
- 封装Retrofit + okhttp + rxjava网络请求框架
- Android okHttp网络请求之Retrofit+Okhttp组合(五)
- Android okHttp网络请求之Retrofit+Okhttp+RxJava组合
- Android okHttp网络请求之Retrofit+Okhttp+RxJava组合
- Android okHttp网络请求之Retrofit+Okhttp+RxJava组合
- Retrofit 2.0 + OkHttp 3.0
- Android网络请求使用Retrofit+OkHttp,如何获取请求参数 ?
- retrofit网络请求参数为json
- Retrofit 2.0使用详解,配合OkHttp、Gson,Android最强网络请求框架
- Retrofit 2.0使用详解,配合OkHttp、Gson,Android最强网络请求框架
- Retrofit 2.0使用详解,配合OkHttp、Gson,Android最强网络请求框架
- Retrofit 2.0使用详解,配合OkHttp、Gson,Android最强网络请求框架
- gcdDepth
- Groovy入门(二)——集合类型-Range
- 单例模式
- Intent的带对象传值
- 剑指Offer--020-顺时针打印矩阵(蛇形打印矩阵)
- Retrofit 2.0 + OkHttp 3.0+JSON网络请求
- SEO分析:都是流量惹的祸
- HotSpot虚拟机对象揭秘之对象的创建过程探究
- Groovy入门(三)——集合类型List
- 数据结构第四章上机实验
- 罪犯转移
- 单片机MQTT实现推送简单使用
- redis服务器模型
- Hive差集运算详解