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

版权声明:本文为博主原创文章,未经博主允许不得转载。

Mvp+RxJava+Retrofit入门教程

Mvp+RxJava+Retrofit现在越来越成熟了,网上的开源项目都在使用这样的框架,所以自己结合一些资料,总结一个简单浅显的例子入门。1.MVPModel View PresenterView ...
  • liduolp
  • liduolp
  • 2017年05月19日 14:23
  • 879

Android 开发一定要看的15个实战项目

实验楼提供了Android在线开发环境,你不需要本地搭建Android开发环境,打开浏览器就可以进行Android开发的学习...
  • shiyanlou_chenshi
  • shiyanlou_chenshi
  • 2016年11月10日 14:25
  • 813

《Android Studio开发实战 从零基础到App上线》出版后记

“盼望着,盼望着,东风来了,春天的脚步近了”——朱自清  人云好事多磨,又云慢工出细活,出一本书不易,出一本原创的技术书籍更是动脑筋。忙忙碌碌将近一年,我的新书《Android Studio开发实战 ...
  • aqi00
  • aqi00
  • 2017年06月08日 00:37
  • 5529

《Android源码设计模式解析与实战》读书笔记(二十六)

第二十六章、MVP应用构架模式1.MVP介绍 MVP模式是MVC模式的一个演化版本,MVP全称Model-View-Presenter。目前MVP在Android应用开发中越来越重要了。 在And...
  • qq_17766199
  • qq_17766199
  • 2016年01月27日 08:58
  • 5515

《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误

资源下载下面是《Android Studio开发实战 从零基础到App上线》一书用到的工具和代码资源:1、本书使用的Android Studio版本为2.2.3,因为Android官网现在不提供该版本...
  • aqi00
  • aqi00
  • 2017年06月11日 21:17
  • 7684

Xamarin Android开发实战(上册)

Xamarin Android开发实战(上册)大学霸内部资料
  • u014621518
  • u014621518
  • 2015年04月02日 10:07
  • 1742

《Android NFC 开发实战详解 》简介+源码+样章+勘误ING

《Android NFC 开发实战详解》简介+源码 SkySeraph Mar. 14th  2014 Email:skyseraph00@163.com ABOUT      哈哈,我的第一本书终于...
  • zgzhaobo
  • zgzhaobo
  • 2014年03月18日 13:36
  • 5765

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

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

学习笔记之《Android项目实战——手机安全卫士》

【Android项目实战-手机安全卫士】 目标:快速积累开发经验,具备中级Android工程师能力。 如遇到难以理解的逻辑或功能,可以先将程序打断点观察程序的执行逻辑。 第一章项目简介:...
  • Liliqianbaidu
  • Liliqianbaidu
  • 2017年04月10日 22:20
  • 976

android性能优化实战前篇

前言:         最近因为某项目cpu,内存的使用率实在让人不敢恭维;手机发烫,电量下降已经让用户无法忍受;频繁快速迭代发版导致各种性能问题突出;由于之前产品不考虑低端手机情况,低端手机直接跑...
  • iamws
  • iamws
  • 2016年06月11日 03:55
  • 6669
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Mvp+Rxjava+Retrofit实战
举报原因:
原因补充:

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