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框架学习实战代码(配合retrofit+dagger2+rxjava)

转载请标明出处,谢谢。 最近一直在学习框架的搭建和使用,对于mvp,很多开发者有自己的独特见解,褒贬不一。不过我还是觉得它有学习的必要。在某些大项目上,使用mvp可以方便后期的代码维护和更新。废话不...

Android中MVP+Retrofit+Rxjava框架的demo

  • 2016年08月15日 15:16
  • 22.85MB
  • 下载

浅谈Android MVP设计模式(简单结合RxJava+Retrofit)

什么是MVP 为什么要用MVP 怎么去完成一个MVP的设计呢 demo实例功能虽小五脏俱全 准备工作 View的基类 presenter的基类 Model的基类 具体的业务实现 转载请指明出处:htt...

Android三大设计模式之一------------------MVP设计模式(包括rxjava+retrofit网络请求框架)

android的开发模式,也就是项目最基本的构建模式,也不是说需要固定不变的模式,在项目中可以灵活运用。 而MVP开发模式属于MVC的变种升级,其相对于mvc模式来说,更高度的解耦,更明确的分工,可...

Android开源项目 MVP+MD+Retrofit+RxJava 看了你会上瘾的

Android开源项目 MVP+MD+Retrofit+RxJava 看了你会上瘾的前言:去年这个时候独立开发上架了一款APP(应用宝:叙恋),用到的技术都是比较老旧。今年趁着回学校写论文的时间,会陆...

MVP+Retrofit+RxJava+Okhttp构造一个合格的Android框架

MVP+Retrofit+RxJava+Okhttp构造一个合格的Android框架写在前面 现在的Android开发需求,是一个快速开发的模式,大部分App都是便捷开发,项目要求1,2个月内就要...

Android mvp+retrofit+rxjava 编程实践(一)--BaseActivity

MVP+RxJava
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Mvp+Rxjava+Retrofit实战
举报原因:
原因补充:

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