自从者我们知道Retrofit会拿返回的json对象映射为我们需要之java对象,我们的采用被一定会为此到很多网络接口,我们今天是请的影片列表,我们还见面呈请电影详情,演员详情等等,那咱们就算待定义MovieDetail、Actor等等Entity。问题是咱们的劳动普通会为我们回到一个永恒体的数额,形如:

最后

若是你认为写更改线程的代码觉得呢不行烦的语,可以把订阅这有的吗卷入起来:

public void getTopMovie(Subscriber<List<Subject>> subscriber, int start, int count){
  //原来的样子
// movieService.getTopMovie(start, count)
// .map(new HttpResultFunc<List<Subject>>())
// .subscribeOn(Schedulers.io())
// .unsubscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(subscriber);

 //修改之后的样子
    Observable observable = movieService.getTopMovie(start, count)
            .map(new HttpResultFunc<List<Subject>>());

    toSubscribe(observable, subscriber);
}

//添加线程管理并订阅
private void toSubscribe(Observable o, Subscriber s){
     o.subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(s);
}

吃你每次写一个求的时段,写的代码尽量少,更多的活力放在工作逻辑本身。

** 2、添加Rxjava并对要过程进展封装 **

1.3 添加Rxjava

Retrofit本身对Rxjava提供了支持。

补加Retrofit对Rxjava的支撑待以Gradle文件被补充加

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'

本来我们已补给加了了。

然后在开立Retrofit的长河被上加如下代码:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

这样一来我们定义之service返回值就未以凡一个Call了,而是一个Observable

又定义MovieService

public interface MovieService {
    @GET("top250")
    Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

getMovie方改呢:

//进行网络请求
private void getMovie(){
    String baseUrl = "https://api.douban.com/v2/movie/";

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();

    MovieService movieService = retrofit.create(MovieService.class);

    movieService.getTopMovie(0, 10)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<MovieEntity>() {
                @Override
                public void onCompleted() {
                    Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(Throwable e) {
                    resultTV.setText(e.getMessage());
                }

                @Override
                public void onNext(MovieEntity movieEntity) {
                    resultTV.setText(movieEntity.toString());
                }
            });
}

诸如此类基本上就得了Retrofit和Rxjava的做,但是自己清楚你们当不会见差强人意的。

对接下去我们管创建Retrofit的长河封装一下,然后想Activity创建Subscriber靶传上皇冠娱乐场。

倘需查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step2

然,以上措施就可以成功请求,但是关押起不抖,我们得以经包装请求方法,在Activity或Fragment中仅保留更新UI相关的逻辑。OK,单纯的包裹比较简单,我们共加入Rxjava来探望。

3.相同格式的Http请求数据统一开展事先处理

既是我们出矣千篇一律的回格式,那么我们恐怕就需要以收获数据后进行一个联的事先处理。

当收到及了一个Http请求结果随后,由于返回的布局统一吗

{
 "resultCode": 0,
 "resultMessage": "成功",
 "data": {}
}

我们怀念如果针对性resultCoderesultMessage事先做一个断定,因为只要resultCode == 0代表success,那么resultCode != 0data一般还是null

Activity或Fragment对resultCoderesultMessage骨干没有趣味,他们只是对求状态data数据感兴趣。

因这种考虑,我们于resultCode != 0的时,抛来个由定义之ApiException。这样尽管见面进去及subscriber的onError中,我们可于onError中处理错误信息。

此外,请求成功时,需要以data数据易为目标数据类型传递给subscriber,因为,Activity和Fragment只想拿到跟她们确实相关的数码。

运用Observable的map方法可以形成这等同效果。

HttpMethods饱受开创一个间类HttpResultFunc,代码如下:

/**
 * 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber
 *
 * @param <T> Subscriber真正需要的数据类型,也就是Data部分的数据类型
 */
private class HttpResultFunc<T> implements Func1<HttpResult<T>, T>{

    @Override
    public T call(HttpResult<T> httpResult) {
        if (httpResult.getResultCode() != 0) {
            throw new ApiException(httpResult.getResultCode());
        }
        return httpResult.getData();
    }
}

然后我们的getTopMovie道改吗:

public void getTopMovie(Subscriber<List<Subject>> subscriber, int start, int count){

    movieService.getTopMovie(start, count)
            .map(new HttpResultFunc<List<Subject>>())
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);
}

由HttpResult中之泛型T就是我们期待传递让subscriber的数据类型,而数可以通过httpResult的getData方法得到,这样咱们便处理了泛型问题,错误处理问题,还有将呼吁数据有离出去为subscriber

然咱们无非待关怀Data数据的门类,而毋庸在关切整个经过了。

内需注意一点,就是在定义Service的早晚,泛型是

HttpResult<User>
//or
HttpResult<List<Subject>>

倘于定义Subscriber的当儿泛型是 java User //or List<Subject>

要不然你见面博得一个转型错误。

若需查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step5

代码中本身是为此豆类数据模拟了HttpResult中的resultCode和resultMessage,与文档中之代码略发出入。

public interface MovieService {
    /** 返回的Observable正是被观察者,我们用来通知观察者对象(这里我们通知UI更新) **/
    @GET("top250")
    Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

4.2 为什么会干Oberver

干Observer的过程是这么的。由于Subscriber一旦调用了unsubscribe方法之后,就不曾因此了。且当事件传递至onError或者onCompleted之后,也会自行的解绑。这样出现的一个题材即是每次发送请求都使创新的Subscriber对象。

这么咱们尽管拿注意力放到了Observer,Observer本身是一个接口,他的特色是无您怎么用,都无见面解绑,为什么吧?因为他从没解绑的道。所以便高达了复用的效应,一开始自我一直喜欢的用Observer。事实上,如果你用的凡Observer,在调用Observable对象的subscribe方法的早晚,会自行的将Observer对象转换成Subscriber对象。

下是源码:

public final Subscription subscribe(final Observer<? super T> observer) {
    if (observer instanceof Subscriber) {
        return subscribe((Subscriber<? super T>)observer);
    }
    return subscribe(new Subscriber<T>() {

        @Override
        public void onCompleted() {
            observer.onCompleted();
        }

        @Override
        public void onError(Throwable e) {
            observer.onError(e);
        }

        @Override
        public void onNext(T t) {
            observer.onNext(t);
        }

    });
}

新兴发现了问题,

问题1 无法取消,因为Observer没有unsubscribe方法 问题2 没有onStart方法
这个一会且

当即半独问题是杀痛苦之。所以,为了后面再好的高潮,我们要选择用Subscriber。

如果data是影视列表,那么我们可以这么描写:

4.争取消一个Http请求 — 观察者之间的对决,Observer VS Subscriber

这就是说封装为泛型后的代码和方的距离不坏,只是将Observable相关的参数或返回路由MovieEntity改也HttpResult<List<Movie>>(注意,我们所用的测试接口和我们上述讨论的构造产生出入),所有就不再贴出代码。

5.2处理ProgressDialog

俺们愿意当cancel掉ProgressDialog的时段,能够取消订阅,也就算销了眼前之Http请求。
所以我们事先来创造个接口来处理当下宗工作。

public interface ProgressCancelListener {
    void onCancelProgress();
}

接下来我们之所以ProgressSubscriber来实现者接口,这样ProgressSubscriber就发出矣一个onCancelProgress方法,在这里面取消订阅。

@Override
public void onCancelProgress() {
    if (!this.isUnsubscribed()) {
        this.unsubscribe();
    }
}

接下来自己为此了一个Handler来封装了ProgressDialog。

public class ProgressDialogHandler extends Handler {

    public static final int SHOW_PROGRESS_DIALOG = 1;
    public static final int DISMISS_PROGRESS_DIALOG = 2;

    private ProgressDialog pd;

    private Context context;
    private boolean cancelable;
    private ProgressCancelListener mProgressCancelListener;

    public ProgressDialogHandler(Context context, ProgressCancelListener mProgressCancelListener,
                                 boolean cancelable) {
        super();
        this.context = context;
        this.mProgressCancelListener = mProgressCancelListener;
        this.cancelable = cancelable;
    }

    private void initProgressDialog(){
        if (pd == null) {
            pd = new ProgressDialog(context);

            pd.setCancelable(cancelable);

            if (cancelable) {
                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        mProgressCancelListener.onCancelProgress();
                    }
                });
            }

            if (!pd.isShowing()) {
                pd.show();
            }
        }
    }

    private void dismissProgressDialog(){
        if (pd != null) {
            pd.dismiss();
            pd = null;
        }
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SHOW_PROGRESS_DIALOG:
                initProgressDialog();
                break;
            case DISMISS_PROGRESS_DIALOG:
                dismissProgressDialog();
                break;
        }
    }
}

Handler接收两个信息来决定显示Dialog还是关闭Dialog。
创建Handler的时节咱们要传入ProgressCancelListener的对象实例。

末贴有ProgressSubscriber的圆代码:

public class ProgressSubscriber<T> extends Subscriber<T> implements ProgressCancelListener{

    private SubscriberOnNextListener mSubscriberOnNextListener;
    private ProgressDialogHandler mProgressDialogHandler;

    private Context context;

    public ProgressSubscriber(SubscriberOnNextListener mSubscriberOnNextListener, Context context) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.context = context;
        mProgressDialogHandler = new ProgressDialogHandler(context, this, true);
    }

    private void showProgressDialog(){
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
        }
    }

    private void dismissProgressDialog(){
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
            mProgressDialogHandler = null;
        }
    }

    @Override
    public void onStart() {
        showProgressDialog();
    }

    @Override
    public void onCompleted() {
        dismissProgressDialog();
        Toast.makeText(context, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(Throwable e) {
        dismissProgressDialog();
        Toast.makeText(context, "error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNext(T t) {
        mSubscriberOnNextListener.onNext(t);
    }

    @Override
    public void onCancelProgress() {
        if (!this.isUnsubscribed()) {
            this.unsubscribe();
        }
    }
}

目前为止,就封装了了。以上是自当用Rxjava和Retrofit过程被踏上了之片坑,最后结合出的,由于并未于事实上的档次遭到跑过,有题目的言辞想能提出来大家讨论一下,拍砖也欢迎。

现在咱们再度写一个初的纱要,步骤是如此的: 1.
Service中定义一个新的章程。 2.
HttpMethods包裹对应之乞求(代码基本好copy) 3.
创建一个SubscriberOnNextListener处理要数据并刷新UI。

observable<HttpResult<List<Movie>>>

5.1处理onNext

咱要这里能够让Activity或者Fragment自己处理onNext之后的逻辑,很自然的我们想到了所以接口。问题或者泛型的题材,这中间我们须指定明确的品类。所以接口还是用泛型。

咱们先来定义一个接口,命名SubscriberOnNextListener

public interface SubscriberOnNextListener<T> {
    void onNext(T t);
}

代码很简短。再来拘禁一下ProgressSubscriber现在底代码

public class ProgressSubscriber<T> extends Subscriber<T> {

    private SubscriberOnNextListener mSubscriberOnNextListener;
    private Context context;

    public ProgressSubscriber(SubscriberOnNextListener mSubscriberOnNextListener, Context context) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.context = context;
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onCompleted() {
        Toast.makeText(context, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(Throwable e) {
        Toast.makeText(context, "error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNext(T t) {
        mSubscriberOnNextListener.onNext(t);
    }
}

自己懂得传Context不好,不过为演示而已,大家可团结包装一下Toast。

MainActivity用是如此的:

先来定义一个SubscriberOnNextListener对象,可以在onCreate里面创建是目标

private SubscriberOnNextListener getTopMovieOnNext;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);

    getTopMovieOnNext = new SubscriberOnNextListener<List<Subject>>() {
        @Override
        public void onNext(List<Subject> subjects) {
            resultTV.setText(subjects.toString());
        }
    };
}

getMovie主意这么写:

private void getMovie(){
 HttpMethods.getInstance().getTopMovie(
  new ProgressSubscriber(getTopMovieOnNext, MainActivity.this), 
  0, 10);
}

这么Activity或Fragment就单需要关怀将到结果以后的逻辑了,其他的一点一滴不用顾虑。

要要查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step6

public interface MovieService {
    /** 以Get方法访问接口,参数start和count分别是对接口地址的传参 **/
    @GET("top250")
    Call<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

1.4 将呼吁过程进行包装

缔造一个靶HttpMethods

public class HttpMethods {

    public static final String BASE_URL = "https://api.douban.com/v2/movie/";

    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit retrofit;
    private MovieService movieService;

    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);

        retrofit = new Retrofit.Builder()
                .client(httpClientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        movieService = retrofit.create(MovieService.class);
    }

    //在访问HttpMethods时创建单例
    private static class SingletonHolder{
        private static final HttpMethods INSTANCE = new HttpMethods();
    }

    //获取单例
    public static HttpMethods getInstance(){
        return SingletonHolder.INSTANCE;
    }

    /**
     * 用于获取豆瓣电影Top250的数据
     * @param subscriber 由调用者传过来的观察者对象
     * @param start 起始位置
     * @param count 获取长度
     */
    public void getTopMovie(Subscriber<MovieEntity> subscriber, int start, int count){
        movieService.getTopMovie(start, count)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }
}

据此一个单例来封装该对象,在构造方法中开创Retrofit和呼应之Service。
如果急需看不同的基地址,那么你也许用创造多个Retrofit对象,或者简直根据不同的驻地址封装不同的HttpMethod类。

俺们回头再来拘禁MainActivity中的getMovie方法:

private void getMovie(){
     subscriber = new Subscriber<MovieEntity>() {
         @Override
         public void onCompleted() {
             Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
         }

         @Override
         public void onError(Throwable e) {
             resultTV.setText(e.getMessage());
         }

         @Override
         public void onNext(MovieEntity movieEntity) {
             resultTV.setText(movieEntity.toString());
         }
     };
     HttpMethods.getInstance().getTopMovie(subscriber, 0, 10);
}        

内部subscriber是MainActivity的成员变量。

倘若需查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step3

observable<HttpResult<HttpResList<List<Movie>>>>

4.1 取消一个Http请求

眼看同样局部我们来聊一下关于取消Http请求的业务,已经Oberver和Subscriber这有限独体位我们谁更爱受咱们G点。

若无应用Rxjava,那么Service返回的是一个Call,而之Call对象来一个cancel方法好用来取消Http请求。那么用了Rxjava之后,如何来取消一个告呢?因为返回值是一个Observable。我们能做的像只有铲除针对Observable对象的订阅,其他的呀啊召开不了。

好以Retrofit已经拉咱着想到了就一点。
答案在RxJavaCallAdapterFactory这个仿佛的源码中得找到

static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
  private final Call<T> originalCall;

  CallOnSubscribe(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  @Override public void call(final Subscriber<? super Response<T>> subscriber) {
    // Since Call is a one-shot type, clone it for each new subscriber.
    final Call<T> call = originalCall.clone();

    // Attempt to cancel the call if it is still in-flight on unsubscription.
    subscriber.add(Subscriptions.create(new Action0() {
      @Override public void call() {
        call.cancel();
      }
    }));

    try {
      Response<T> response = call.execute();
      if (!subscriber.isUnsubscribed()) {
        subscriber.onNext(response);
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (!subscriber.isUnsubscribed()) {
        subscriber.onError(t);
      }
      return;
    }

    if (!subscriber.isUnsubscribed()) {
      subscriber.onCompleted();
    }
  }
}

咱俩看看call方法被,给subscriber添加了一个Subscription对象,Subscription对象好粗略,主要就取消订阅用的,如果你查看Subscriptions.create的源码,发现是这般的

public static Subscription create(final Action0 unsubscribe) {
  return BooleanSubscription.create(unsubscribe);
}

动用了一个BooleanSubscription类来创造一个Subscription,如果您点进去看BooleanSubscription.create方法漫天就是清楚了,当接触绑定的时段,subscriber会调用Subscription的unsubscribe方法,然后触发创建Subscription时候的传递进入的Action0的call方法。RxJavaCallAdapterFactory帮我们吃subscriber添加之凡call.cancel(),

总结起来就是,我们当Activity或者Fragment中创造subscriber对象,想只要注销请求的时调用subscriber的unsubscribe方法就得了。

抱歉这无异节发生无限多之SubscriberSubscription以及ObserverObservable,老衲就拘留的时候吗是不理解吐了小坏了,习惯了即好了。

https://api.douban.com/v2/movie/top250?start=0&count=10

2.同一格式的Http请求数据该怎么封装

老二有些与老三有的自己参考了知乎上之一个问答: RxJava+Retrofit,在联网返回后如何先行进行统一之判断? 不过没有完整的演示,所以当及时写一个完好无损的示范出来。

以此段子我们来聊一下聊Http服务返回一个固定格式的数码的题材。 例如:

{
 "resultCode": 0,
 "resultMessage": "成功",
 "data": {}
}

多数底Http服务或都是这么设置,resultCode和resultMessage的情相对比较稳定,而data的情变化多端,72换都未肯定够变的,有或是单User对象,也发出或是只订单对象,还来或是独订单列表。
按照我们前的用法,使用Gson转型要我们在创造subscriber对象是指定返回值类型,如果我们针对不同的归来值进行打包的话,那或就使出过多单Entity了,看正在明显凡是格外清晰的构造,却盖data的不确定性无奈了起。

豆蔻年华,不必烦恼,来来来~ 老衲赐你宝典葵花,老衲就是练了是才出家。。。

咱俩可创造一个HttpResult类

public class HttpResult<T> {
    private int resultCode;
    private String resultMessage;

    private T data;
}

若是data是一个User对象的话语。那么以定义Service方法的归来值就是得描绘为

Observable<HttpResult<User>>

这样一来HttpResult就相当给一个包装类,将结果包装了起,但是当采用的上要为有一个明确的型。

每当上头的言传身教中,我哉创了一个HttpResult类,用来学这个形式,将内的Subject单独封装了四起。

public class HttpResult<T> {

    //用来模仿resultCode和resultMessage
    private int count;
    private int start;
    private int total;
    private String title;

    //用来模仿Data
    private T subjects;
}

然泛型的早晚就要写啊:

Observable<HttpResult<List<Subject>>>

只要需要查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step4

设想到一般列表的多少都见面发出分页信息,我们照例可以持续封装:

RxJava 与 Retrofit 结合的超级实践

作者:tough1985

感 DaoCloud 为作者供的 500 RMB 写作赞助:

皇冠娱乐场 1

成帮助方 /初步做

假使data是Actor对象的讲话,那么定义Service方法返回值就可以描绘成:

说到底的终极

倘您的httpResult格式本身没有问题,但是data中之情节是这么的:

{
 "resultCode": 0,
 "resultMessage": "成功",
 "data": {"user": {}, "orderArray": []}
}

这么的情事还能够无克继承采用这样的框架为?
我的缓解方式是包一个像样,把user和orderArray作为类的性能。
但是一旦你的服务器一会data本身是一个完好无损的user数据,一会同时是这般: "data": {"user": {}, "orderArray": []} 那自己道您生必不可少跟你的服务端好聊聊了,请他自恃顿饭和顿酒,大莫了贡献有菊花就是了。

而如果服务已经上线了!!!

对不起,骚年……

老衲会在公坟前念300不折不扣Thinking in java同而超度之~

盼而用Retrofit和Rxjava的初体位能够享受到新的高潮。

 

 

转载请标明出处:http://www.jianshu.com/p/86cf7de684b3

1.RxJava如何与Retrofit结合

private void getMovie() {
        String baseUrl = "https://api.douban.com/v2/movie/";
        /** 创建Retrofit对象,数据转换使用Gson **/
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        /** 通过MoviceService得到Call,然后加入请求队列并,并在Callback接口方法中处理返回结果 **/
        MovieService movieService = retrofit.create(MovieService.class);
        Call<MovieEntity> call = movieService.getTopMovie(0, 10);
        call.enqueue(new Callback<MovieEntity>() {
            @Override
            public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
                resultTV.setText(response.body().toString());
            }

            @Override
            public void onFailure(Call<MovieEntity> call, Throwable t) {
                resultTV.setText(t.getMessage());
            }
        });
    }

5.一个急需ProgressDialog的Subscriber该有的则

我们期待生一个Subscriber在我们每次发送请求的上能弹来一个ProgressDialog,然后以求接受的下给这ProgressDialog消失,同时在咱们撤销这ProgressDialog的同时能取消时底乞求,而我辈仅仅待处理中的数目就是得了。

俺们先行来创造一个类,就深受ProgressSubscriber,让他继续Subscriber

Subscriber给咱提供了onStart、onNext、onError、onCompleted四个措施。

中只有onNext方法返回了数,那我们当然希望会以onNext里面处理数量有关的逻辑。

onStart办法我们就此来启动一个ProgressDialog。 onError主意我们集中处理错误,同时为停下ProgressDialog onComplated法中已ProgressDialog

内部我们需要解决简单单问题

题材1 onNext的处理 问题2 cancel不见一个ProgressDialog的下取消请求

咱俩事先来缓解问题1

public class HttpMethods {
    public static final String BASE_URL = "https://api.douban.com/v2/movie/";
    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit retrofit;
    private MovieService movieService;

    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);

        retrofit = new Retrofit.Builder()
                .client(httpClientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                //此处添加RxJavaCallAdapterFactory,把请求结果直接映射为
                //MovieService接口方法返回的具体类型MovieEntity
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        movieService = retrofit.create(MovieService.class);
    }

    //在访问HttpMethods时创建单例
    private static class SingletonHolder{
        private static final HttpMethods INSTANCE = new HttpMethods();
    }

    //获取单例
    public static HttpMethods getInstance(){
        return SingletonHolder.INSTANCE;
    }

    /**
     * 用于获取豆瓣电影Top250的数据
     * @param subscriber  由调用者传过来的观察者对象
     * @param start 起始位置
     * @param count 获取长度
     */
    public void getTopMovie(Subscriber<MovieEntity> subscriber, int start, int count){
        movieService.getTopMovie(start, count)
                //指定subscribe()发生在io调度器(读写文件、读写数据库、网络信息交互等)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                //指定subscriber的回调发生在主线程
                .observeOn(AndroidSchedulers.mainThread())
                //实现订阅关系
                .subscribe(subscriber);
    }
}

1.2 只用Retrofit

我们准备在getMovie方式被开展网络要,我们事先来探视就以Retrofit大凡怎进行的。

咱俩应用豆瓣电影之Top250召开测试连接,目标地点为

https://api.douban.com/v2/movie/top250?start=0&count=10

有关返回的数码格式,大家温馨看下链接就是来看了,太长就非放上了。

第一我们只要因返回的结果封装一个Entity,暂命名为MovieEntity,代码就非粘了。

连片下去我们要创造一个接口取名为MovieService,代码如下:

public interface MovieService {
    @GET("top250")
    Call<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

回到MainActivity里,我们来写getMovie方的代码

//进行网络请求
private void getMovie(){
    String baseUrl = "https://api.douban.com/v2/movie/";

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    MovieService movieService = retrofit.create(MovieService.class);
    Call<MovieEntity> call = movieService.getTopMovie(0, 10);
    call.enqueue(new Callback<MovieEntity>() {
        @Override
        public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
            resultTV.setText(response.body().toString());
        }

        @Override
        public void onFailure(Call<MovieEntity> call, Throwable t) {
            resultTV.setText(t.getMessage());
        }
    });
}

上述为无经包装的、原生态之Retrofit写网络要的代码。
我们得包创建Retrofit和service部分的代码,然后Activity用创造一个Callback作为参数为Call,这样Activity中唯有关注请求的结果,而且Call有cancel方法可收回一个请,好像没Rxjava什么事了,我认为可以写到立刻便收工了~

接下去我们如果当的题目是这般的
如果我的Http返回数据是一个联结之格式,例如

{
 "resultCode": 0,
 "resultMessage": "成功",
 "data": {}
}

咱俩安对回结果进行一个合并之处理呢?

另外,我的ProgressDialog的show方法应该当哪调用啊?看样子只能以getMovie()这个法子中调用了,换个地方发出请求就如于对应之Listener里面写一不折不扣show()的代码,其实大苦恼。

再就是荒唐请求我吗想集中处理掉不要贴还的代码。

咱们事先来拘禁结合了Rxjava之后,事情发生没发变化之也许。当然就是并非Rxjava,依旧能够开多底卷入,只是于费心。

比方要查看项目代码 –> 代码地址:

https://github.com/tough1985/RxjavaRetrofitDemo

选择Tag -> step1

observable<HttpResult<Actor>>

1.1 基本页面

先扔出build.gradle文本的情

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.0'
    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    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.google.code.gson:gson:2.6.2'
    compile 'com.jakewharton:butterknife:7.0.1'
}

也就是说本文是基于RxJava1.1.0以及Retrofit 2.0.0-beta4来进展的。
添加rxandroid是以rxjava中之线程问题。

下面先增建筑一个核心的页面,页面很简短,先来拘禁文件目录结构皇冠娱乐场 2

activity_main.xml的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".activity.MainActivity">

    <Button
        android:id="@+id/click_me_BN"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:padding="5dp"
        android:text="点我"
        android:textSize="16sp"/>
    <TextView
        android:id="@+id/result_TV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/click_me_BN"
        android:text="Hello World!"
        android:textSize="16sp"/>
</RelativeLayout>

MainActivity.java的代码如下:

package com.queen.rxjavaretrofitdemo.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.TextView;

import com.queen.rxjavaretrofitdemo.R;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.click_me_BN)
    Button clickMeBN;
    @Bind(R.id.result_TV)
    TextView resultTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.click_me_BN)
    public void onClick() {
        getMovie();
    }

    //进行网络请求
    private void getMovie(){

    }
}

只顾不要忘记加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

嘿什么什么,是匪是来一致种植碟中谍、局中局的感觉…当然,为了减小层级,我们可以拿分页的连锁消息涉及resultCode这个层级来,这个要我们跟服务端协定好一个平整。

前言

RxJava和Retrofit也生气了一段时间了,不过最近直在就学ReactNative和Node相关的相,一直尚未时间研究这些新东西,最近产生只种类准备写,打算先用Android写一个Demo出来,却发现Android的社会风气有了不安的更动,EventBus和OKHttp啥的都不翼而飞了,RxJava及Retrofit是什么不良?

吓吧,到Github上耐着性看罢了RxJava和Retrofit的牵线及几个Demo,原来Android的慌神Jake
Wharton为Retrofit这个类型贡献了如此多之代码,没有道理不用了。

使您针对RxJava不熟悉请先押于 Android 开发者的 RxJava
详解立马首文章。

如若您针对Retrofit不熟悉就先行押Retrofit官网。

本为产生很多RxJava与Retrofit的章,但是我认为多豪门都不行纠结的力量还未曾于总出,所以才产生了这个篇稿子。

迎接大家拍砖。

接下去进入正文,我是打下面几乎只角度去思辨RxJava与Retrofit结合的。

  1. RxJava如何与Retrofit结合
  2. 平等格式的Http请求数据该如何封装
  3. 如出一辙格式的Http请求数据统一进行预处理
  4. 怎么样取消一个Http请求 — 观察者之间的对决,Oberver VS Subscriber
  5. 一个用ProgressDialog的Subscriber该有则

据此,协定好一个业内、好用之数据结构,是何等的酸爽。

那么电影列表,就用这么形容了:

c、那么getMovie()方法直接调用封装了之getTopMovie()即可。从中,我们看来运Rxjava带来两接触转:一个凡将请封装进Observable;另外是由此落实Subscriber中之老三只接口方法来通知请求状态(即UI更新)。

/** 支持分页的json结构 **/
{
 "start": 0,
 "count": 20,
 "total": 250
 "list": []
}
/** 封装后带分页的泛型对象 **/
public class HttpResList<T> {
    private int start;
    private int count;
    private int total;
    private T list;
}

b、把要的经过封装到HttpMethods类里面,

首先,本篇是冲这个的总、思考和进展,那篇作者由浅入深,徐徐道来,读起来感觉那个硬。

   private void getMovie() {
        subscriber = new Subscriber<MovieEntity>() {
            @Override
            public void onCompleted() {
                Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(Throwable e) {
                resultTV.setText(e.getMessage());
            }

            @Override
            public void onNext(MovieEntity movieEntity) {
                /** 这里得到的请求结果直接是我们想要的java对象 **/
                resultTV.setText(movieEntity.toString());
            }
        };
        HttpMethods.getInstance().getTopMovie(subscriber, 0, 10);
    }

再就是我们通常会预先去判断resultCode,以便可以统一处理错误信息。至于data中之构造,则是转变的,它好是影视列表Movies,也可是优信息Actor,那么这我们即便见面回忆使用泛型来进展打包:

实在,我一直闹个疑惑,为什么而就此Rxjava呢?没顾代码简洁、好用啊,是呀,Why?请动
煮 Retrofit 论 RxJava(二)。

c、接着,在界面中以Retrofit进行网络要:

a、网络接口使用豆瓣电影之top250,我们根据其回到的json格式封装为一个MovieEntity。

a、我们前定义的Service返回值就由于Call变为Observable了。

public class HttpResult<T> {
    private int resultCode;
    private String resultMsg;
    private T data;
}
{
 "resultCode": 1,
 "resultMsg": "成功",
 "data": {}
}

b、然后创建接口MovieService:

** 1、使用Retrofit来进行网络要 **

相关文章