您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Android 网络开源库之-retrofit
 
作者:全世界-gl 来自于:CSDN 发布于 2016-1-25
  2008  次浏览      17
 

前言

当前的网络开源库有许多,如volley,okhttp,retrofit等,这三个库当前是比较火的,其中,okhttp和retrofit由square团队开发。关于这三个库的区别,请移步stackoverflow或者知乎查看。开发过程中选择什么样的开源库需要更具我们APP来做出选择。我们选出stackoverflow中的一段话来看下。

上面说,需要与web service通信的时候,我们使用retrofit。百度百科 web service介绍,那么我们见天就来了解下retrofit。

什么是retrofit

关于什么是retrofit,官网文档上们有一句话。A type-safe HTTP client for Android and Java。额,似乎什么也看出去来,就知道是一个类型安全的http client库。那么什么是类型安全呢?类型安全代码指访问被授权可以访问的内存位置。例如,类型安全代码不能从其他对象的私有字段读取值。它只从定义完善的允许方式访问类型才能读取。类型安全的代码具备定义良好的数据类型。更多内容百度百科-类型安全,关于这里还引用上面知乎的一句话。

上面这么多抽象的概念太抽象,我们不管他。我们只需要知道retrofit确实是个很好的开源库就可以了。

入门打老虎

开源库是不错,但是,你文档能不能写的详细点。入门就是个大老虎。怎么说呢,文档给出的代码精辟,但是不能运行。那么,我们来看看具体的,真正的入门步骤。

1.在gradle脚本中添加

compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

retrofit是中有用的okhttp,添加gson库是为了将返回数据转化为实体类。

2.将http api转化为java接口

以下称这货为http接口

比如我们想去这个网址上获取json数据。https://api.github.com/users/Guolei1130

你们也可以将Guolei1130替换为你们自己的github。

public interface gitapi {
@GET("/users/{user}")
Call<gitmodel> getFeed(@Path("user") String user);
}

这里使用注解,@GET表示我们的请求方式是get请求,@GET(“STR”),标明这里的请求地址为BASEURL+STR,{user},这里会在后面被getFeed的user参数替换,最后就拼接成了最终的请求路径。返回的数据室什么呢。Call< gitmodel>,这里返回的Call是用来让我们执行请求的。需要注意的是:Call< T>表示返回体中的数据,我们看下上面那个网址的返回数据。

很明显是个json对象。

但是如果是返回数据为json数组的话我们就需要注意,这里具体怎么用还要根据返回数据以及我们的model来确定,倘若model对应json中的对象,便用Call< List< gitmodel>>,倘若对应json数组,用Call< gitmodel>。多的不说了,自己体会体会。

3.model的编写

只需要将json对象的键值,编写model对应的成员变量,在生成get set方法就好。

如图:

4.执行请求

Retrofit retrofit= new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
gitapi service = retrofit.create(gitapi.class);
Call<gitmodel> model = service.getFeed("Guolei1130");
model.enqueue(new Callback<gitmodel>() {
@Override
public void onResponse(Response<gitmodel> response, Retrofit retrofit) {
Log.e(TAG, "onResponse: "+response.body().getLogin() );
}

@Override
public void onFailure(Throwable t) {
Log.e(TAG, "onFailure: " + t.getMessage());
}
});

这里我们先构造Retrofit对象,由于我们将返回的json数据转化成了model对象,所以在构造Retrofit对象的时候,通过addConverterFactory来添加转化器来完成数据转化。

然后利用http接口的方法生成Call对象,最后用Call对象来执行http请求(异步和同步,后面会说到)。别忘记添加权限。

好,到这里入门老虎就被我们打死了。

注解爽歪歪

我们既然知道了retrofit是通过注解将HTTP转化为java接口,那么我们就需要了解下都有哪些注解,该怎么用。

请求方式

GET, POST, PUT, DELETE, 和 HEAD,我们平常开发中经常用的也就get和post。关于HTTP请求方式,这里就不再说了,网上有很多介绍HTTP协议的文章,都特别详细。

我们知道get请求方式,参数是放在路径当中的。看下图的路径。

是不是很长,不过没关系,用retrofit一样可以将这么长的串拼接到路径中,怎么做呢?

这里就用到了@Query(一个键值对)和@QueryMap(多对键值对)。

// 假设 baseurl = "http://baidu.com"
@GET("/s")
Call<gitmodel> onekey(@Query("wd") String wdvalue);

上面代码拼接出来的 = “http://baidu.com/s?wd=wdvalue“.

上面只是一个参数的时候,很多时候我们有许多参数,这个时候就需要我们使用@QueryMap 了

Call<gitmodel> manykey(@QueryMap Map<String, String> options);

上面的即可将多对键值对拼接到路径当中。

请求体

我们知道post和get的区别当中有一点就是参数的位置,get放在url路径当中,post放在请求体当中。

注意:前方高能,请仔细阅读。前方高能,请仔细阅读。前方高能,请仔细阅读。下面我们模拟一个登录,请求参数为用户名和密码,返回参数为我们的用户名。

1.转化为接口

@POST("/index.php")
Call<Des> post(@Body User user);

2.编写User和Des,用 来转化数据

public class Des {
public String des;

public String getDes() {
return des;
}

public void setDes(String des) {
this.des = des;
}
}


public class User {
public String username;
public String password;

public User(String username,String password){
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

3.发送请求

Retrofit retrofit= new Retrofit.Builder()
// .baseUrl("https://api.github.com")
.baseUrl("http://192.168.1.214")
.addConverterFactory(GsonConverterFactory.create())
.build();

gitapi service = retrofit.create(gitapi.class);
Call<Des> model = service.post(new User("guolei","123456"));
model.enqueue(new Callback<Des>() {
@Override
public void onResponse(Response<Des> response, Retrofit retrofit) {
Log.e(TAG, "onResponse: "+response.body().getDes());
}

@Override
public void onFailure(Throwable t) {
Log.e(TAG, "onFailure: "+t.getMessage() );
}
});

客户端的代码很简单,在这里就不做过多的解释。重点在于客户端和服务器之间的交互。妈蛋,坑死我了。官方文档上有一句话是这样说的。

意思就是请求体对象也会转化为json,刚开始我们并不知道会转化为json,我们还傻傻的在php代码中$_POST[‘username’],试了几次没效果之后。果断拿出工具来分析。

抓包神器Charles,关于如何使用我这里不说,我这里只说下如何设置android端代理。长按链接的网络-》修改 网络-》将代理设为手动,输入IP和端口。如下图:

接下来,我们利用抓包工具去看看服务器接受的数据。如下图:

果然,是json数据,但是我擦,我们明显感觉这种数据我们没法通过$_POST来接收。怎么办呢,不着急,咱们可以通过如下代码来接收。php完整代码如下(ps:只是演示,没几行)

<?php 

$var=file_get_contents("php://input");

$obj= json_decode($var,true);
$des = $obj['username'];
$arr = array("des"=>$des);
echo json_encode($arr);

恩,就这么少,关于如下安装php开发环境就不说了,so easy不是么。最后,我们来看下效果图:

表单编码和多part

什么叫表单,我想大家都应该知道,表单中有很多元素,我们这里也不例外。在html代码中,我们经常通过form表单来提交。在上面的请求体中,我们明显感觉那玩意十分貌似有点难用。不过没关系,我们有表单。

还是和上个例子一样。

@FormUrlEncoded
@POST("/index.php")
Call<Des> form(@Field("username") String username,@Field("password") String password); Call<Des> model = service.form("guolei","123456");

看下输出结果;

这个多part是什么呢,就是将请求提分为多个部分,这个就没啥好说了的。

请求头

我们知道http是有请求头的,有些时候我们是需要填写或者配置一下请求头的,比如说,文件上传,或者cookie保持。这里的请求头支持动态配置和静态配置。

1.静态配置

通过@Headers注解。如:下面这段是官方文档上的。

@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})

2.动态配置

也来一段官方文档上面的吧。

@GET("/user")
Call<User> getUser(@Header("Authorization") String authorization)

这些都相对简单的,没啥好说的,事实上,在开发过程中需要我们配置请求头的地方也不多。

执行方式

这里支持异步和同步。上面的例子中我们都是用的异步。那么我们看下如何执行同步请求,也很简单。

//同步请求
//model.execute().body().getLogin();

混淆代码

-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions

retrofit+rxjava

在抛物线大大的RxJava入门当中,我们知道了retrofit和rxjava可以结合使用,那么我们现在便来看看如何使用。

1.添加

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'io.reactivex:rxjava:1.0.16'
compile 'io.reactivex:rxandroid:1.0.1'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
}

2.http api接口

@FormUrlEncoded
@POST("/index.php")
public Observable<Des> rxpost(@Field("username") String username,@Field("password") String password);

3.在retrofit中添加RxJavaCallAdapterFactory

Retrofit retrofit= new Retrofit.Builder()
// .baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl("http://192.168.1.214")
.build();

4.执行

gitapi service = retrofit.create(gitapi.class);
Observable<Des> observable = service.rxpost("quanshijie", "123456");
observable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread())
.subscribe(new Action1<Des>() {
@Override
public void call(Des des) {
Log.e(TAG, "call: " + des.getDes().toString());
mText.setText(des.getDes().toString());
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.e(TAG, "call: " + throwable.getLocalizedMessage());
}
});

在这里我们要做好线程调度,现在网络上那些坑爹的代码,少一行代码,把我坑了好长时间。喵了个咪的。最后看下效果图。

总结

到这里,还差我们网络请求的其他需求,比如说文件上传下载,cookie保持,https协议支持等。在okhttp中,这些东西都可以,retrofit作为okhttp的兄弟,我想也不会太差,还得继续学习啊。

不过,在查了一些资料之后,我们知道,网络库的选择要根据需求,一个很大的项目中用一个网络库很显然是不可能的。那么,okhttp+retrofit+图片缓存库+rxjava会不会成为日后开发的主流呢。还是期待吧。

好累啊,到现在饭都没吃。retrofit的坑还是有的。我估计剩下的三点地方坑更大,不扯了,收工。

   
2008 次浏览       17
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   

Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...