Android Mvp+Rxjava+Retrofit实战

原创 2016年08月13日 10:53:12

Android Mvp+Rxjava+Retrofit实战

目录结构

这里写图片描述

build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.orhanobut:logger:1.8'
    compile 'io.reactivex:rxjava:1.1.7'
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
}

Rxjava+Retrofit统一Http的封装

HttpService

Retrofit的配置

public interface HttpService {
    /**
     * 测量多点之间的直线距离
     *
     * @param waypoints 需要测距的点的经纬度坐标;需传入两个或更多的点。两个点之间用 “; ”进行分割开,单个点的经纬度用“,”分隔开;例如: waypoints=118
     *                  .77147503233,32.054128923368;116.3521416286, 39.965780080447;116
     *                  .28215586757,39.965780080447
     * @param ak
     * @param output
     * @return
     */
    @FormUrlEncoded
    @POST("distance?")
    Observable<BaseHttpResult<List<String>>> getDistance(@Field("waypoints") String waypoints,
                                                         @Field("ak") String ak,
                                                         @Field("output") String output);
}

HttpUtil

Retrofit和Rxjava进行结合 封装网络请求类

public class HttpUtil {
    /**
     * 超时时间
     */
    private static final int DEFAULT_TIMEOUT = 10;
    /**
     * retrofit
     */
    private Retrofit retrofit;
    /**
     * 接口请求
     */
    private HttpService httpService;

    public HttpService getHttpService() {
        return httpService;
    }

    private HttpUtil() {
        //创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        //添加迭代器
        httpClientBuilder.addInterceptor(new LoggerInterceptor());
        retrofit = new Retrofit.Builder()
                .client(httpClientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(StaticCode.BASE_URL)
                .build();
        httpService = retrofit.create(HttpService.class);
    }

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

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

    /**
     * 组装Observable
     *
     * @param observable
     */
    public Observable packageObservable(Observable observable) {
        return observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取网络数据不转化
     *
     * @param observable
     */
    public Subscription sendHttp(Observable observable, HttpSubscriber listener) {
        return packageObservable(observable)
                .subscribe(listener);
    }

    /**
     * 获取网络数据转化
     *
     * @param observable
     */
    public <T> Subscription sendHttpWithMap(Observable observable, HttpSubscriber<T>
            listener) {
        return observable.compose(this.<T>applySchedulers())
                .subscribe(listener);
    }

    /**
     * Observable 转化
     *
     * @param <T>
     * @return
     */
    <T> Observable.Transformer<BaseHttpResult<T>, T> applySchedulers() {
        return new Observable.Transformer<BaseHttpResult<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseHttpResult<T>> baseHttpResultObservable) {
                return baseHttpResultObservable.map(new HttpFunc<T>())
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 用来统一处理Http请求到的数据,并将数据解析成对应的Model返回
     *
     * @param <T> Subscriber真正需要的数据类型
     */
    private class HttpFunc<T> implements Func1<BaseHttpResult<T>, T> {

        @Override
        public T call(BaseHttpResult<T> baseHttpResult) {
            //获取数据失败则抛出异常 会进入到subscriber的onError中
            if (!baseHttpResult.getStatus().equals(StaticCode.HTTP_RESPONSE_SUCCESS))
                throw new RuntimeException(baseHttpResult.getStatus());

            return baseHttpResult.getResults();
        }
    }
}

LoggerInterceptor

日志打印和请求头的增加

public class LoggerInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request().newBuilder().addHeader("version", "1.0")
                .addHeader("clientSort", "android").addHeader("Charset", "UTF-8")
                .build();

        printRequestLog(originalRequest);
        Response response = null;
        try {
            //发送网络请求
            response = chain.proceed(originalRequest);
            printResult(response);
        } catch (SocketTimeoutException e) {
            //此处不抛异常  连接超时会crash 没有找到其他好的方法
            e.printStackTrace();

        }
        return response;
    }

    /**
     * 打印请求日志
     *
     * @param originalRequest
     * @return
     * @throws IOException
     */
    private void printRequestLog(Request originalRequest) throws IOException {
        FormBody.Builder formBuilder = new FormBody.Builder();
        String msg = originalRequest.url() + "\n";
        RequestBody oidBody = originalRequest.body();
        if (oidBody instanceof FormBody) {
            FormBody formBody = (FormBody) oidBody;
            for (int i = 0; i < formBody.size(); i++) {
                String name = URLDecoder.decode(formBody.encodedName(i), "utf-8");
                String value = URLDecoder.decode(formBody.encodedValue(i), "utf-8");
                if (!TextUtils.isEmpty(value)) {
                    formBuilder.add(name, value);
                    msg += name + "  =  " + value + "\n";
                }
            }
        }
        Logger.i(msg);
    }
    /**
     * 打印返回日志
     *
     * @param response
     * @throws IOException
     */
    private void printResult(Response response) throws IOException {
        ResponseBody responseBody = response.body();
        BufferedSource source = responseBody.source();
        source.request(Long.MAX_VALUE); // Buffer the entire body.
        Buffer buffer = source.buffer();
        Charset UTF8 = Charset.forName("UTF-8");
        MediaType contentType = responseBody.contentType();
        if (contentType != null) {
            UTF8 = contentType.charset(UTF8);
        }
        String a = buffer.clone().readString(UTF8);
        Logger.i(a);
    }

}

BaseHttpResult

 public class BaseHttpResult<T> {
    public String status;

    private T results;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public T getResults() {
        return results;
    }

    public void setResults(T results) {
        this.results = results;
    }
}

HttpSubscriber

Rxjava的回调

public abstract class HttpSubscriber<T> extends Subscriber<T> {

    /**
     * 请求标示
     */
    private int tag;

    public HttpSubscriber(int tag) {
        this.tag = tag;
    }

    @Override
    public void onCompleted() {
        _complete();
    }

    @Override
    public void onError(Throwable e) {
        _complete();
        onError(e.getMessage(), tag);
    }

    @Override
    public void onNext(T t) {
        onSuccess(t, tag);
    }

    public abstract void onSuccess(T t, int tag);

    public abstract void onError(String msg, int tag);

    public abstract void _complete();

}

Mvp的加入

MvpView

public interface MvpView {

    void showLoadingDialog();

    void dismissLoadingDialog();

}

IBasePresenter

public interface IBasePresenter<V extends MvpView> {

    void subscribe();

    void unsubscribe();

}

BasePresenter

对Presenter公共部分进行初始化
public abstract class BasePresenter

使用示例

MainActivity

Activity中实现View

public class MainActivity extends AppCompatActivity implements MainContract.IMainView {


    private MainPre mainPre;
    private android.widget.TextView getDistance;
    private android.widget.TextView firstToSecondDistance;
    private android.widget.TextView secondToThreeDistance;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.secondToThreeDistance = (TextView) findViewById(R.id.second_to_three_distance);
        this.firstToSecondDistance = (TextView) findViewById(R.id.first_to_second_distance);
        this.getDistance = (TextView) findViewById(R.id.get_distance);

        mainPre = new MainPre(this);

        getDistance.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mainPre.subscribe();
            }
        });
    }

    @Override
    public void setFirstPointToSecondPointDistance(String distance) {
        firstToSecondDistance.setText(distance);
    }

    @Override
    public void setSecondPointToThreePointDistance(String distance) {
        secondToThreeDistance.setText(distance);
    }

    @Override
    public void showLoadingDialog() {
        //这边可以做Dialog的显示
        Logger.e("请求开始");
    }

    @Override
    public void dismissLoadingDialog() {
        //这边可以做Dialog的隐藏
        Logger.e("请求结束");
    }
}

MainContract

public class MainContract {
    /**
     * Created by huangweizhou on 16/8/10.
     */

    public interface IMainView extends MvpView {
        /**
         * 第一个点和第二个点之间的距离
         *
         * @param distance
         */
        void setFirstPointToSecondPointDistance(String distance);

        /**
         * 第二个点和第三个点之间的距离
         *
         * @param distance
         */

        void setSecondPointToThreePointDistance(String distance);
    }
}

MainPre

presenter中绑定对应的View和解析的类型

public class MainPre extends BasePresenter<MainContract.IMainView, List<String>> {
    public MainPre(MainContract.IMainView view) {
        super(view);
    }

    @Override
    public void onSuccess(List<String> strings, int tag) {
        baseView.setFirstPointToSecondPointDistance(strings.get(0));
        baseView.setSecondPointToThreePointDistance(strings.get(1));
    }

    @Override
    public void onError(String msg, int tag) {
        Logger.e(msg);
    }


    @Override
    public void subscribe() {
        sendHttpWithMap(httpService.getDistance("118.77147503233,32.054128923368;\n" +
                "     116.3521416286,39.965780080447;116.28215586757,39\n" +
                "     .965780080447", "6cyEpstfAo1HSFGPSeshRXa459p3TyT0", "json"));
    }
}

StaticCode

public class StaticCode {

    /**
     * Java地址
     */
    public static final String BASE_URL = "http://api.map.baidu.com/telematics/v3/";

    /**
     * 获取网络数据成功
     */
    public static final String HTTP_RESPONSE_SUCCESS = "Success";

}

源码地址

Mvp-RxJava-Retrofit

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hwz1023/article/details/52198146

优雅的使用MVP+RxJava+Retrofit框架

前面我已经写过一篇关于Google的RxJava版MVP解读的文章,本篇就是我在此基础上进行了修改和封装,稍微变化一下,见上图。目的是让这个框架更加实用,同时简化操作,少写代码。果然程序员都是喜欢偷懒...
  • u011622280
  • u011622280
  • 2017-01-12 17:20:58
  • 2306

练手项目 | 基于MVP+RxJava2+Retrofit2的资讯类App

本文作者作者:Horrarndoo链接:http://www.jianshu.com/p/6ef9e3804395本文由作者投稿发布。如果你刚好需要一些练手的项目,希望对你有用~很早之前就想写一个个人...
  • u013651026
  • u013651026
  • 2018-01-29 10:19:20
  • 121

带你高效学习MVP+RxJava+Retrofit

引言自上次用老旧的mvc做了一个仿微信项目之后,我给自己做了一个短期的规划,先把MVP+RxJava+Retrofit这新的安卓三剑客给学了,于是,经过一个多星期的折腾,总算是对MVP+RxJava+...
  • CSDN_LQR
  • CSDN_LQR
  • 2017-03-01 10:09:03
  • 1042

简易Mvp+RxJava2+Retrofit2 搭建一个属于自己的开发框架

一:序言 2016年安卓热门词汇MVP,RxJava,Retrofit。时隔一年这些框架依然是很常用的,现在来把这几个关键词整合起来,搭建一个快速开发框架。。。 二: MVP是什么...
  • LouisZhoun
  • LouisZhoun
  • 2017-10-12 10:39:09
  • 1137

MVP+Rxjava+Retrofit

  • 2017年03月28日 18:24
  • 22.55MB
  • 下载

Android——MVP+Retrofit2.0+RxJava框架整合

对三者的学习已经有一段时间了,现在写了一个基础版本的整合Demo,因为下个项目就要正式开始了,这段时间会不断对该Demo进行扩展补充。 Demo的Github地址:https://github.com...
  • qq_22770457
  • qq_22770457
  • 2016-09-27 22:48:52
  • 2863

Mvp+RxJava2+Retrofit2 搭建一个属于自己的开发框架

许多不管怎么做、怎么想都没结果的事,要懂得交给时间。有些事无论你怎么努力怎么勉强,时间不够,还是耐心的等待吧。 一:序言 2016年安卓热门词汇MVP,RxJava,Retrof...
  • a_zhon
  • a_zhon
  • 2017-09-09 11:30:00
  • 5367

Mvp+Rxjava2+Retrofit2完美封装

  • 2017年11月11日 15:07
  • 389KB
  • 下载

使用RxJava+Retrofit+MVP+Glide开发一个简单的新闻客户端

好久没有更新博客了,有点懒。。之前在网上看到很多有趣又高效的开源库,于是就想着写一个简单的项目来运用这些开源库,恰巧看见聚合数据上有个新闻头条的API,所以就尝试写了一下。先上效果图:在这个小项目中,...
  • u010429311
  • u010429311
  • 2016-11-18 12:37:39
  • 1674

学习项目: mvp+Rxjava+Retrofit

源码下载地址:https://github.com//panjichang/weishijie-develop 集视频,图片和文章的娱乐app,数据来源于优酷,暴走tv,全球动画精选以及其他网站。 ...
  • jdsjlzx
  • jdsjlzx
  • 2016-04-29 15:54:48
  • 2556
收藏助手
不良信息举报
您举报文章:Android Mvp+Rxjava+Retrofit实战
举报原因:
原因补充:

(最多只允许输入30个字)