Retrofit网络框架入门使用
1.简单介绍
retrofit事实上就是对okhttp做了进一步一层封装优化。
我们仅仅须要通过简单的配置就能使用retrofit来进行网络请求了。
Retrofit能够直接返回Bean对象,比如假设我们进行一个网络接口的请求。返回来一串json字符串。那么这个时候一般我们都要拿到这个json字符串后进行解析得到相应的Bean对象,Retrofit仅仅要依赖一下Gson的转换库然后进行简单的配置就能够直接拿到Bean对象了,不须要我们自己去解析。
接触过OKHttp的人会发现,Retrofit和OKHttp的代码有些地方有很大的类似度。
他的性能很的棒,国外大牛(被墙了)已经做过測例如以下图:
看了这个图之后你有什么想法?
Talk is cheap, show me the code!
!
2.高速使用
在实际项目开发中get、post请求使用居多。那我们以get请求来做个入门小案例。
http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8
以上连接是一个get请求方式。參数在地址后面使用“?”进行名值对的拼接。请求的结果是一个json字符串数据。例如以下
{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.8.8.8"}}
来个简单的Demo界面例如以下:
功能很easy,一个输入框输入IP地址,然后获取IP地址所在的国家。
1)环境的配置
如今预计很少人用eclipse做项目开发了。eclipse的方式就不另赘述了(GitHub上也是有jar依赖下载的)。我们这里的开发工具是用的Android Studio,在 GitHub项目地址:https://github.com/square/retrofit能够找到Gradle的依赖代码:
加入两个依赖:retrofit依赖。和gson转换器。
compile 'com.squareup.retrofit2:retrofit:2.1.0'//眼下最新的版本号
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//加入好这个依赖后我们就能够进行数据转换器的配置了。retrofit内部就会帮我们去转换json字符串为Java对象
在AS里面的效果例如以下:
converter-gson依赖的版本号号与retrofit依赖版本号号保持一致。我们在GitHub上能够看到。他们在同一个project里面的。
2)代码
布局很easy就不另贴代码了。类也不多參看以下的包结构图
Retrofit操作步骤
① 先把接口返回来的数据bean对象写好。
能够直接使用工具转化。如GsonFormat工具
public class IpInfo {
public int code;
public DataBean data;
public static class DataBean {
public String country;
public String country_id;
public String area;
public String area_id;
public String region;
public String region_id;
public String city;
public String city_id;
public String county;
public String county_id;
public String isp;
public String isp_id;
public String ip;
}
}
② 定义API接口
一般来讲都是处理遵循RESTful接口规范的http接口,我们须要把接口转化为Java Interface。
/**
* 这个接口就是普通的借口类,可是看到里面的方法来,会有一些注解定义相关的功能
* 如@GET定义请求方式为get请求方式,假设有參数能够使用@Query、@QueryMap定义
*/
public interface IpService {
/**
* @return 固定返回值为Call。当中泛型指定是进行请求后返回终于得数据类型。
*/
@GET("getIpInfo.php") //@GET 定义网络请求方式
Call<IpInfo> getIpInfo(@Query("ip") String ip); //@Query("ip") 指的是传入的參数名为ip。值为调用方法传入的值形參ip
}
③ 初始化Retrofit,创建接口实例,进行异步请求
代码凝视灰常仔细了
/**
*Retrofit简单有用案例
*
* 採用http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.2 地址进行查询
*/
public class MainActivity extends AppCompatActivity {
public static final String baseUrl = "http://ip.taobao.com/service/";
private TextView tvResult;
private EditText etIp;
IpService ipService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = (TextView) findViewById(R.id.tv_result);
etIp = (EditText) findViewById(R.id.et_ip);
initRetrofit();
}
/**
* 初始化Retrofit实例。并创建接口类。
* 注意:IpService不须要我们去实现。直接Retrofit=类有create方法生成。
*/
private void initRetrofit() {
//创建Retrofit的实例,把Gson转换器设置下
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(baseUrl)//设置API的基础地址
.addConverterFactory(GsonConverterFactory.create())//设置后才才支持json字符串转化为Bean
.build();
//使用Retrofit的create方法传入创建接口实例
ipService = retrofit.create(IpService.class);
}
/**
* 布局中查询button配置的点击事件
* @param view
*/
public void check(View view) {
String ip = etIp.getText().toString();
if (TextUtils.isEmpty(ip)) {
Toast.makeText(this, "ip 不能为空", Toast.LENGTH_SHORT).show();
return;
}
//调用接口声明的方法
Call<IpInfo> ipInfoCall = ipService.getIpInfo(ip);
//call能够直接调用异步方法。进行结果获取。
须要传入接口回调Callback,
ipInfoCall.enqueue(new Callback<IpInfo>() {
@Override
public void onResponse(Call<IpInfo> call, Response<IpInfo> response) {
//推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。
否则连接失败
if (response.isSuccessful()) {
//直接拿到JavaBean
IpInfo ipInfo = response.body();
//这里直接能够进行UI操作。OKHttp是不行的哦
tvResult.setText(ipInfo.getData().getCountry());
} else {
//请求失败。
假设代码执行到这里来说明是有跟后台握手的,是后台处理有问题,如404(没有资源),500(后台报错了)
tvResult.setText("查询失败!! -->code="+response.code());
}
}
@Override
public void onFailure(Call<IpInfo> call, Throwable t) {
//请求失败。如,没有声明网络权限、没有网络、或者是Retrofit 异常内部处理异常(如Gson解析失败)也是会到这里
t.printStackTrace();
tvResult.setText("查询失败:"+t.getCause());
}
});
}
}
3.经常使用注解
GET:get 请求方式
POST:post请求方式
Query:定义get请求參数
QueryMap:定义get请求參数
Field:定义post请求參数
FieldMap:定义post请求參数
Header:定义头參数
HeaderMap:定义头參数
Headers:定义头參数
Path:动态路径
来看看代码是怎么实现的:
public interface SampleApi {
//----------------------GET 请求方式 start --------------------------------
/**
* 注解:GET。QUERY,QUERYMAP 的使用
*/
/**
* get 请求固定參数形式
*
* @return
*/
@GET("demo?
username=zhanghsan&password=123455")
Call<SampleResponse> getFun();
/**
* 使用@Query注解进行參数传递
*
* @param username
* @param password
* @return
*/
@GET("demo")
Call<SampleResponse> getFun(@Query("username") String username, @Query("password") String password);
/**
* 使用@QueryMap注解 Map集合进行參数传递
*
* @param params
* @return
*/
@GET("demo")
Call<SampleResponse> getFun(@QueryMap Map<String, Object> params);
//----------------------GET 请求方式 end --------------------------------
//----------------------POST 请求方式 start --------------------------------
/**
* POST,Field,FieldMap,FormUrlEncoded(POST 方式请求有參数的时候一定不要忘记了这个注解)
*/
/**
* post使用@Query注解进行參数传递
*
* @param username
* @param password
* @return
*/
@FormUrlEncoded
@POST("demo")
Call<SampleResponse> postFun(@Field("username") String username, @Field("password") String password);
/**
* POST使用@FiledMap Map集合进行參数传递
*
* @param params
* @return
*/
@FormUrlEncoded
@POST("demo")
Call<SampleResponse> postFun(@FieldMap Map<String, Object> params);
//----------------------POST 请求方式 end --------------------------------
//----------------------head參数加入start --------------------------------
/**
* Headers。Header,HeaderMap
* */
/**
* 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下
*
* @param username
* @param password
* @return
*/
@Headers(
{"os:Android"
, "osversion:5.0"
})
@FormUrlEncoded
@POST("demo")
Call<SampleResponse> postFunWithHead(@Field("username") String username, @Field("password") String password);
/**
* 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下
*
* @param username
* @param password
* @return
*/
@FormUrlEncoded
@POST("demo")
Call<SampleResponse> postFunWithHead(@Header("os") String os, @Header("osversion") String osversion, @Field("username") String username, @Field("password") String password);
/**
* 有些接口须要传送一些操作client系统的信息,比方系统类型,系统版本号等例如以下
*
* @param headParams head 參数。键值对的形式存储到map集合中去
* @param username
* @param password
* @return
*/
@FormUrlEncoded
@POST("demo")
Call<SampleResponse> postFunWithHead(@HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password);
//----------------------head參数加入end --------------------------------
//----------------------path 注解 --------------------------------
/**
* Path注解使用时在请求方式注解后面的URL设置一个占位符,使用大括号包裹。
在方法形參类型前使用@Path("占位符")。
*/
@FormUrlEncoded
@POST("{path}")
Call<SampleResponse> postFunWithHead(@Path("path") String path, @HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password);
}
Activity代码
public class SampleActivity extends AppCompatActivity {
EditText etName;
EditText etPassword;
TextView tvResult;
SampleApi sampleApi;
SampleCallBack callback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
etName = (EditText) findViewById(R.id.et_name);
etPassword = (EditText) findViewById(R.id.et_password);
tvResult = (TextView) findViewById(R.id.tv_result);
//使用链式调用建立
sampleApi = new Retrofit
.Builder()
.baseUrl("http://10.0.2.2:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(SampleApi.class);
callback = new SampleCallBack();
}
/**
* button点击事件
*
* @param view
*/
public void submit(View view) {
tvResult.setText("正在请求....");
String name = etName.getText().toString();
String password = etPassword.getText().toString();
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "參数不能为空", Toast.LENGTH_SHORT).show();
return;
}
Call<SampleResponse> call;
switch (view.getId()) {
case R.id.btn_get:
call = sampleApi.getFun(name, password);
call.enqueue(callback);
break;
case R.id.btn_post:
call = sampleApi.postFun(name, password);
call.enqueue(callback);
break;
case R.id.btn_head:
// call = sampleApi.postFunWithHead(name, password);//第一种,直接静态定义方式。看接口方法
// call = sampleApi.postFunWithHead("ios","10.10.10",name, password);//另外一种,能够动态配置值得方式
Map<String, String> map = new HashMap<>();
map.put("os", "android");
map.put("osversion", "9.9.9999999");
// call = sampleApi.postFunWithHead(map, name, password);//第三种,能够动态配置參数和值得形式
call = sampleApi.postFunWithHead("demo",map, name, password);//第四种,结合Path定义路径
call.enqueue(callback);
break;
}
}
/**
* @param result
* 显示结果
*/
public void showResult(String result) {
tvResult.setText(result);
}
/**
* 回调实现类
*/
public class SampleCallBack implements Callback<SampleResponse> {
@Override
public void onResponse(Call<SampleResponse> call, Response<SampleResponse> response) {
//推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。否则连接失败
if (response.isSuccessful()) {
//直接拿到JavaBean
SampleResponse sampleResponse = response.body();
//这里直接能够进行UI操作。OKHttp是不行的哦
showResult(sampleResponse.toString());
} else {
//请求失败。
假设代码执行到这里来说明是有跟后台握手的,是后台处理有问题,如404(没有资源),500(后台报错了)
showResult("查询失败。! -->code=" + response.code());
}
}
@Override
public void onFailure(Call<SampleResponse> call, Throwable t) {
//请求失败。如。没有声明网络权限、没有网络、或者是Retrofit 异常内部处理异常(如Gson解析失败)也是会到这里
t.printStackTrace();
showResult("查询失败:" + t.getCause());
}
}
}
执行效果
4.URL操作注意事项
拼接注意,建议baseUrl用“/”结尾。接口中请求方式后面的url不用”/”开头
样例:baseUrl=http://10.0.2.2:8080/market/ url=home
错误案例
案例一:
baseUrl=http://10.0.2.2:8080/market url=home
—>http://10.0.2.2:8080/home
分析:默认用最后一个斜线去拼接
案例二:
baseUrl=http://10.0.2.2:8080/market url=/home
—>http://10.0.2.2:8080/home
分析:url中開始的斜线代表主机地址http://10.0.2.2:8080
Retrofit还能够实现上传下载以及 结合RxJava使用,等下回分解!
Retrofit网络框架入门使用的更多相关文章
- 开源框架相关面试问题-retrofit网络框架面试问题讲解
retrofit使用简介: 在retrofit中通过一个接口作为Http请求的api接口.注意:@GET("url")中的url只是一个路径,不包含主机号的. 创建一个retrof ...
- android快捷开发之Retrofit网络加载框架的简单使用
大家都知道,安卓最大的特点就是开源化,这自然会产生很多十分好用的第三方API,而基本每一个APP都会与网络操作和缓存处理机制打交道,当然,你可以自己通过HttpUrlConnection再通过返回数据 ...
- 结合Retrofit,RxJava,Okhttp,FastJson的网络框架RRO
Retrofit以其灵活的调用形式, 强大的扩展性著称. 随着RxAndroid的推出, Retrofit这样的可插拔式的网络框架因其可以灵活兼容各种数据解析器, 回调形式(主要还是RxJava啦)而 ...
- Android网络框架之Retrofit + RxJava + OkHttp 变化的时代
1.什么是Retrofit框架? 它是Square公司开发的现在非常流行的网络框架,所以我们在导入它的包的时候都可以看到这个公司的名字,目前的版本是2. 特点: 性能好,处理快,使用简单,Retrof ...
- RxJava+Retrofit+OkHttp,一步一步封装网络框架;
使用RxJava+Retrofit+OkHttp,首先在build.gradle添加: compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com ...
- Android网络框架源码分析一---Volley
转载自 http://www.jianshu.com/p/9e17727f31a1?utm_campaign=maleskine&utm_content=note&utm_medium ...
- Android网络框架比较
今天,公司需要为一个安卓app选择一个合适的网络框架,具体我了解,主要的安卓网络框架有okhttp,retrofit,android-async-http,volley. 查找网上的资料,大致可以得到 ...
- 【原创】NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
概述 本文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo. 当前由于NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能. ...
- 【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同 ...
随机推荐
- yield from (python生成器)
#生成器中的yield from是干什么用的(一般多用于线程,协程那)def func(): # for i in 'AB': # yield i yield from 'AB' # 就相当于上面的f ...
- CSS 样式的优先级(重要,一定要理解)
1. 同一元素引用了多个样式时,排在后面的样式属性的优先级高 例如,下面的 div,同时引用了 [.default] 和 [.user] 中的样式,其中 [.user] 样式中的 width 属性会替 ...
- 【Leetcode 3】Longest Substring Without Repeating Characters0
Description: Given a string, find the length of the longest substring without repeating characters. ...
- Objective-C——Runtime理解
动态语言 OC是一门不折不扣的动态语言,所以它的很多机制都是动态运行时决定的.这点和C语言不一样,C语言是静态绑定,也就是编译后所有的一切都已经决定了.这一点和C语言的函数指针有些类似,很多时候函数指 ...
- C#语言最基础的认识变量
变量是指一块存储数据的内存空间,并且该内存区域的数据内容可以发生变化. 变量是必须先声明后赋值. 基本的语法:数据类型+变量名: 变量名=数据: 简单的使用技巧:声明赋值简写 Static void ...
- Android 8.0 启动后台service 出错 IllegalStateException: Not allowed to start service Intent
错误原因: Android 8.0 不再允许后台service直接通过startService方式去启动, 具体行为变更如下: 如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况 ...
- 一个.py引用另一个.py中的方法
处理函数 X_Add_Y_Func.py #__author__ = 'Administrator' def add_func(x, y): return x+y 调用函数 X_Add_Y_Func_ ...
- Less——less基本安装
1.下载node.js 我们需要NodeJ运行LESS示例. 要下载NodeJ,请打开链接https://nodejs.org/en/ 2.node.js安装是否正确 在cmd中输入lessc -v, ...
- (转)分布式文件存储FastDFS(三)FastDFS配置
http://blog.csdn.net/xingjiarong/article/details/50559768 在上一节中我们一起搭建了一个单节点的FastDFS系统,但是仅仅将系统搭建起来是远远 ...
- TCP报文到达确认(ACK)机制
TCP数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节流中每个字节的编号.一个TCP数据包中包含多个字节 ...