Android -- RxAndroid and Retrofit 2.0学习笔记
RxAndroid and Retrofit 2.0
一
关于Rx的学习我参考了这篇博客,是我在网上看到的博客中写的比较全的
http://blog.csdn.net/meegomeego/article/details/49155989/
Retrofit 2.0还是测试版, 主要是‘领导’说Retrofit 比okHttp 和 Volley要好,今天弄了下,例子是照retrofit官网敲的。
http://square.github.io/retrofit/
二
设计还在弄设计图,闲的没什么事,翻译一下retrofit的官网吧
Retrofit
A type-safe HTTP client for Android and Java(蛋疼,这句怎么翻译)
Introduction
Retrofit让你的http api 变成java接口1
2
3
4public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit会生成一个GitHubService接口的实现1
2
3
4
5Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
每一个GitHubService的回调,都会make一个同步或者异步的http请求到远程的webserver1
Call<List<Repo>> repos = service.listRepos("octocat");
使用注解去描述http请求
- url参数支持替换和查询
- 对象转换到请求体
- 复合的请求体和文件上传
API Declaration
注解的方法和他的参数怎样处理一个请求
REQUEST METHOD
每一个方法必须有一个http的注解,他提供了一个请求的方法和一个相对的url。一共有5中注解GET, POST, PUT, DELETE, and HEAD。资源的相对url在注解中规定1
@GET("users/list")
还可以指定url的查询参数
1
@GET("users/list?sort=desc")
URL MANIPULATION
一个请求的url中的参数和blocks可以被动态的替换,这个blocks要被{}包围。这个参数要使用@Path注解,并且使用同一个字符1
2@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
查寻参数也可以被添加1
2@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
对于相对复杂的查询参数也可以使用map1
2@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
REQUEST BODY
使用@Body注解可以指定一个对象作为HTTP请求体。1
2@POST("users/new")
Call<User> createUser(@Body User user);
这个对象也可以使用一个Retrofit的实例指定的一个转换器转换,如果没有添加这个转换器,就会使用RequestBody(没看懂)
FORM ENCODED AND MULTIPART
方法也可以用来生命发送表单编码和符合数据
表单编码的数据发送当@FormUrlEncoded存在的方法。每个键-值对注释@Field包含名称和对象提供的价值。1
2
3@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
多部分请求时使用@Multipart存在的方法。部分使用@Part注释声明。1
2
3
4@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description")
RequestBody description);
部分部件采用改造的转换器,也可以实现RequestBody处理自己的序列化。
HEADER MANIPULATION
可以使用@Headers注释的方法设置静态头。1
2
3@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
1 | @Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App"}) |
注意,头不会互相覆盖。具有相同名称的所有头文件都包括在请求
END
后面的说的就不往上粘了,因为我也看不懂
在运行例子的时候遇见了一些问题,当时看了一些其他的博客,GitHubService 是作为参数回掉的,返回值是空,运行的过程提示GitHubService 的返回值不能使空了, 不知道是不是2.0和之前的差别
接下来就是在Rx中使用Retrofit了
三
按照官网的做法
创建了一个GitHubService,这个接口简单的写了两个方法,第一个方法在RX中使用了Retrofit,要注意的就是每个请求前面都是/1
2
3
4
5
6
7
8public interface GitHubService
{
@GET("/{users}/mobilesiri")
Observable<Repo> getUser(@Path("users") String user);
@GET("/users/mobilesiri")
Call<Repo> getUser2();
}
这里没使用官网上给的api接口,用的是https://api.github.com/users/mobilesiri
官网上面的数据太多了,然后用JsonFromat生成了一个bean 叫 1
2
3
接着就是主要的内容了
baseUrl是请求的通用的部分,这里设定的就是
private static final String URI = “https://api.github.com";1
2
3
4
5
6
7addConverterFactory 这个是设置用Gson转换,也可以自定义, 但自定义这个后面再说吧
addCallAdapterFactory 这个在Rx中使用的话要添加
还有提个坑就是这个依赖,一定要对应,版本不对,网又不好,在这弄了半天
```gradle
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
Rx也跟最新的版本就行了1
2
3
4
5Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URI)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
1 | GitHubService gitHubService = retrofit.create(GitHubService.class); |
以上是没有用Rx的代码
下面就是在Rx中使用Retrofit的代码了,完成一次网络请求,从实现上来说还是很简单的1
2
3
4
5
6
7gitHubService.getUser("users").subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Repo>() {
@Override
public void call(Repo repo) {
}
});
subscribeOn 指定的是observe运行线程;observeOn是subscribe的运行线程,呃……
当然subscribe中new 一个 Subscriber去实现1
2
3
4
5
6
7
8
9
10
11
12
13以上就是在Rx中使用Retrofit做网络请求的基本方法了
——————————————————————————————--
# RxAndroid
##### Observable (被观察者)
##### Subscribers (订阅者)
Observable 我理解成了事件的发送者,Subscribers为事件的处理,这样方便理解吧……默背十遍,记住这两个概念,省得记混。
下面就照网上的教程敲一个小例子吧!!!
### 一、尝试
* 导入rx所需要的包
```android
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
- 大概的思路是创建一个消息的发送者和接收者,然后将他们链接起来,和大象一样,也是分三步:
第一个例子啥也不说了,直接上代码
1 | package tiny.rxandrioddemo; |
二、继续尝试
看到了rx中有from just ……这些东西, 看看这个是干嘛的吧, 之后一顿百度:
rx提供了一些快捷创建事件队列的方式,就上上面一行中提到的just和from了
- just(T…): 将传入的参数依次发送出来。
- from(T[])/ from(Iterable<? extends T>): 将传入的数组或 Iterable拆分成具体对象后,依次发送出来。
依然还是先上代码了,上面的方法简化成下边这样1
2
3private void createObservable() {
mObservable = Observable.just("ha1", "ha2", "ha3");
}
程序调用了三次doNext 一次 onComleted
再将上面的代码改成这样, 也是ok的1
2
3
4
5
6
7private void createObservable(){
List<String> eventList = new ArrayList<>();
eventList.add("haha1");
eventList.add("haha2");
eventList.add("haha3");
mObservable = Observable.from(eventList);
}
三、呃……还是尝试
和上面一样,事件的发送者简化了,那么还想简化一下事件的处理,之后发现了actionx 这个方法,那么就改一下createSubscriber()1
2
3
4
5
6
7
8private void createSubscriber(){
mSubscriberAction = new Action1<String>(){
@Override
public void call(String s){
Log.d(TAG, "call: " + s);
}
};
}
下面是输出结果
三、迷之变幻
- map(): 事件对象的直接变换,可以将一个对象转变成另一个对象。它是 RxJava 最常用的变换
- flatMap():这个事件比较复杂,就举个网上的例子来说明吧
参考了博客http://blog.csdn.net/daditao/article/details/50606228
首先假设这么一种需求:假设有一个数据结构『学生』,现在需要打印出一组学生的名字。实现方式很简单:
很简单。那么再假设:如果要打印出每个学生所需要修的所有课程的名称呢?(需求的区别在于,每个学生只有一个名字,但却有多个课程。)首先可以这样实现:
我哟啊是不想用for循环来输出也可以这么写
这样就简单了
具体详细的可以看上面链接中的博客,就比较全面了
- Funcx:在变换中,使用了Funcx这个方法,这个方法同Actionx一样理解,但是Funcx一些列的方法是带有返回值的
四、线程切换
写代码测试之后,发现RxAndroid 中可以使用observeOn 方法来切换线程,但是还没有摸清subscribeOn方法是干什么用的。
之前以为observeOn是设置Observable的运行线程;而subscribeOn是规定了subscribe的线程
总结:初学到这了,基本上可以拿Rxandroid写一个例子,在写例子的时候在慢慢学习Rx吧
大概一个月之前看了看Retrofit进行网络接口, 这把手里的这个应用的网络层改成Retrofit,但是公司的应用,请求的时候都要改header和post,弄了一下,随后就又开始加班了(艹)。之前打的都快忘了,还是趁着空闲的时间先记下来吧。
1 | package tiny.rxandrioddemo.mkmy.net.net; |