Rxjava+Retrofit 入门

Retrofit

Retrofit 是什么

Retrofit 是一个通过注解将 REST API 转换成 Java 接口的函数库。特点
* 要求服务端接口遵守 REST 规范
* 可以自动把返回的字符串解析成 GSON 实体
* 默认搭配 GSON 和 OkHttp 使用
* 支持 Rxjava,可以直接返回 Oservable

拼接 url

Retrofit 通过注解转换接口。主要两个部分:在 retrofit 中设置主机地址;在 Server 接口中设置方法和参数。

常用的注解:
* POST/GET 请求方式
* PATH 路径中的占位符
* Query/QueryMap 请求参数,会在 url 后面直接拼接 “?key=value&key1=vaule2…”
* Field/FieldMap 请求参数,只能在 post 中使用,且要配合 @FromUrlEncoded 使用,会把参数添加到请求体中

关于在接口中使用注解可见 https://blog.csdn.net/jasonwang18/article/details/68486709

以下代码实现了 “http://47.96.165.11:8080/ncgctest/SandPlantScreen/getAll.json?name=山” 的 url。

public interface SandplantServer {
    @GET("{function}.json")
    Call<String> getSandplantByName(@Path("function") String function,@Query("name") String sandplantName);
}


Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://47.96.165.11:8080/ncgctest/SandPlantScreen/")
                .build();
Call<String> stringCall=retrofit.create(SandplantServer.class).getSandplantByName("getAll","山");
接收回调

retrofit 接收三种方式的回调:字符串,GSON 解析的实体类,RxJava 的 Oservable 对象。在 Retrofit 中设置:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://106.3.227.33/pulamsi/")
    //增加返回值为String的支持
    .addConverterFactory(ScalarsConverterFactory.create())
    //增加返回值为Gson的支持(以实体类返回)
    .addConverterFactory(GsonConverterFactory.create())
    //增加返回值为Oservable<T>的支持
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();

这三种方式分别需要依赖:

compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'//ConverterFactory的Gson依赖包
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'//CallAdapterFactory的Rx依赖包
compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'//ConverterFactory的String依赖包
完整代码:
public interface SandplantServer {
    @GET("{function}.json")
    Call<String> getSandplantByName(@Path("function") String function,@Query("name") String sandplantName);
}

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://47.96.165.11:8080/ncgctest/SandPlantScreen/")
        //增加返回值为String的支持
        .addConverterFactory(ScalarsConverterFactory.create())
        .build();

    SandplantServer mSandplantServer=retrofit.create(SandplantServer.class);
    Call<String> stringCall=mSandplantServer.getSandplantByName("getAll","山");
    stringCall.enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            Log.i("hhhhh", "onResponse: "+response.body());
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            Log.i("hhhhh", "onFailure: ",t);
        }
    });

RxJava

RxJava 是使用观察者模式来实现的一个响应式框架,用于处理异步操作。

观察者模式

以为一个 Button 设置 OnClickListener 为例,Button 是被观察者,OnClickListener 是观察者,setOnClickListener 这一动作称为订阅,OnClickListener 中的 onClick 方法为事件。

RxJava 的观察者模式
  • 被观察者 Observable
  • 观察者 Observer
  • 订阅 subscribe()
  • 事件 onNext(),onCompleted(),onError()

RxJava 内置了一个实现了 Observer 的抽象类:Subscriber 。Subscriber 中增加了两个方法 onStart() 和 unsubscribe() ,分别用于在事件发送前调用和取消订阅。

实际上,在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。

普通使用
//观察者
final Observer<String> observer=new Observer<String>() {
    //事件
    @Override
    public void onCompleted() {
        Log.i(TAG, "onCompleted: ");
    }

    @Override
    public void onError(Throwable e) {
        Log.i(TAG, "onError: ",e);
    }

    @Override
    public void onNext(String s) {
        Log.i(TAG, "onNext: "+s);
    }
};

//被观察者
Observable observable=Observable.create(new Observable.OnSubscribe() {
    @Override
    public void call(Object o) {
        observer.onNext("1");
        observer.onNext("2");
        observer.onNext("3");
        observer.onCompleted();
    }
});

//订阅
observable.subscribe(observer);
事件变换

RxJava 的一大特点是事件变换,他可以将事件序列中的事件进行加工变换,转换成不同的事件序列,从而实现分步骤处理复杂的事务。基本原理就是通过拦截旧的事件,处理后重新发送新的事件。

ActionX 和 FuncX

ActionX 是 RxJava 的一系列接口,它只有一个方法 call(),这个方法无返回值,参数个数为 X。这个系列的方法可以被用以包装不同的无返回值的方法。通常用于包装 subscribe 中的 onNext(),onCompleted(),onError() 方法,作为一个参数传入 subscribe() 以实现不完整定义的回调,RxJava 会自动根据定义创建出 Subscriber。

FuncX 系列方法与 ActionX 相似,但是有返回值的,所以被用以包装不同的有返回值的方法。通常在事件变换的时候使用,用以返回其他类型的事件。

示例:

Observable.just("images/logo.png") // 输入类型 String
    .map(new Func1<String, Bitmap>() {
        @Override
        public Bitmap call(String filePath) { // 参数类型 String
            return getBitmapFromPath(filePath); // 返回类型 Bitmap
        }
    })
    .subscribe(new Action1<Bitmap>() {
        @Override
        public void call(Bitmap bitmap) { // 参数类型 Bitmap
            showBitmap(bitmap);
        }
    });

常用的变换:
* map() 事件对象直接变换,从一个事件转换成另一个事件
* flatMap() 把一个事件转换成一个 Observable,通过激活传入的 Observable 并把发送的事件传入新的 Observable 中并统一交给 Subscriber 。可用于一对多的转换,并可以嵌套异步的代码。
* throttleFirst() 在每次事件触发后丢弃一定时间间隔内的新的事件,可用作去抖动过滤
* zip() 有三个参数,可以把两个队列合并到一个中。

线程控制

RxJava 支持异步的关键就是线程调度器 Scheduler ,RxJava 中的调度器:
* Schedulers.immediate() 在本线程执行
* Schedulers.newThread() 新建线程执行
* Schedulers.io() 读写使用的线程,在一个线程池中使用空闲线程进行,网络请求一般也使用此线程
* Schedulers.computation() 计算使用的线程,使用一个跟 CPU 核数相同的线程池
* AndroidSchedulers.mainThread() Android 专用的主线程

在 Observable 中使用 subscribeOn 和 observeOn 分别设置事件产生的线程和事件消费的线程。subscribeOn 只能调用一次,而 observeOn 可以调用多次,在变换之前调用可以指定每次变换所在的线程。

Rxjava+Retrofit

依赖

implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'//ConverterFactory的String依赖包
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'//ConverterFactory的Gson依赖包
implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'//CallAdapterFactory的Rx依赖包


implementation 'io.reactivex:rxjava:1.1.0'//Rx的包
implementation 'io.reactivex:rxandroid:1.1.0'//Rx的包
public class DataBean<T> {
    private String msg;
    private int code;
    private List<T> data;
}

public class SandplantBean {
    private String name;
    private int userId;
}

public class UserBean {
    private int userId;
    private String userName;
    private String realName;
    private String mobile;
}
public interface SandplantServer {

    @GET("SandPlantScreen/{function}.json")
    Observable<DataBean<SandplantBean>> getSandplantObservable(@Path("function") String function,@Query("name") String sandplantName);

    @GET("sysUserScreen/find.json")
    Observable<UserBean> getUser(@Query("userId") int userId);

}
    private void getSandPlantOwner() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://47.96.165.11:8080/ncgctest/")
                //增加返回值为String的支持
                .addConverterFactory(ScalarsConverterFactory.create())
                //增加返回值为Gson的支持(以实体类返回)
                .addConverterFactory(GsonConverterFactory.create())
                //增加返回值为Oservable<T>的支持
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        final SandplantServer mSandplantServer = retrofit.create(SandplantServer.class);

        mSandplantServer.getSandplantObservable("getAll", "山")
                //把一个 DataBean 转换成一个 List<SandplantBean>
                .map(new Func1<DataBean<SandplantBean>, List<SandplantBean>>() {
                    @Override
                    public List<SandplantBean> call(DataBean<SandplantBean> sandplantBeanDataBean) {
                        return sandplantBeanDataBean.getData();
                    }
                })
                //把一个 List<SandplantBean> 转换成一个 SandplantBean 队列
                .flatMap(new Func1<List<SandplantBean>, Observable<SandplantBean>>() {
                    @Override
                    public Observable<SandplantBean> call(List<SandplantBean> sandplantBeans) {
                        return Observable.from(sandplantBeans);
                    }
                })
                //根据 SandplantBean 获取其 UserBean,此操作需要从后台获取数据,是异步操作
                .flatMap(new Func1<SandplantBean, Observable<UserBean>>() {
                    @Override
                    public Observable<UserBean> call(SandplantBean sandplantBean) {
                        return mSandplantServer.getUser(sandplantBean.getUserId());
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<UserBean>() {
                    @Override
                    public void call(UserBean userBean) {
                        if (userBean==null){
                            return;
                        }
                        Log.i(TAG, "call: " + userBean.toString());
                    }

                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        Log.i(TAG, "call: ",throwable);
                        Toast.makeText(MainActivity.this, "数据错误", Toast.LENGTH_SHORT).show();
                    }
                });

    }

以上代码实现了一下操作:
1. 从后台获取 Sandplant 信息,并解析成 DataBean
2. 从 DataBean 中获取 List
3. 把 List 转换成 SandplantBean 队列
4. 对于每个 SandplantBean 根据其 userId 从后台获取相应的 UserBean
5. 打印获取到的 UserBean 信息

参考的文章:

https://www.daidingkang.cc/2016/06/17/Retrofit2-network-framework-parsing/

https://gank.io/post/560e15be2dca930e00da1083

https://blog.csdn.net/johnny901114/article/details/51524470

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值