装逼开始之前,为大家推荐两篇文章,用来更好的学习Retrofit和Rxjava。在这里我们要感谢互联网装逼行业勇于献身,甘于奉献的的大婶们。我仅代表个人,给您们跪舔了。

Retrofit:Retrofit官网

Rxjava:给 Android 开发者的 RxJava 详解

---------------这是分割线---------------

首先配置支持的gradle文件:

    compile 'io.reactivex:rxjava:1.1.3'    compile 'io.reactivex:rxandroid:1.1.0'    compile 'com.squareup.retrofit2:retrofit:2.0.1'    compile 'com.squareup.retrofit2:converter-gson:2.0.1'    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'

截止至本文发表前,上述支持库都是最新版本。

贴出Retrofit官网的GET请求示例:GitHubService接口

public interface GitHubService {  @GET("users/{user}/repos")  Call> listRepos(@Path("user") String user);}

网络请求部分代码为:

        String baseUrl = "https://*******";        Retrofit retrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .addConverterFactory(GsonConverterFactory.create())                .build();        GitHubService service = retrofit.create(GitHubService.class);        Call> repos = service.listRepos("octocat");        repos.enqueue(new Callback() {            @Override            public void onResponse(Call call, Response response) {                Log.i("onResponse",response.body().toString());            }            @Override            public void onFailure(Call call, Throwable t) {                Log.i("onResponse",t.getMessage());            }        });


baseUrl 为网络请求地址

addConverterFactory(GsonConverterFactory.create())为设置json解析方式为Gson。

retrofit.create采用动态代理的方式获取GitHubService对象,并通过Callback获取返回的数据。

---------------当Retrofit与Rxjava相遇----------------


Retrofit.Builder需要调用

.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
方法,表示用Rxjava做回调,即Rxjava所讲的观察者模式。那么网络请求接口就需要改成如下方式:
Observable> listRepos(@Path("user") String user);
网络请求部分的代码则更改为:

        String baseUrl = "https://*******";        Retrofit retrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .addConverterFactory(GsonConverterFactory.create())                .build();        service.listRepos("octocat")                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Subscriber() {                    @Override                    public void onCompleted() {                        Log.i("onCompleted","onCompleted");                    }                    @Override                    public void onError(Throwable e) {                        Log.i("onError",e.toString());                    }                    @Override                    public void onNext(XXXEntity movieEntity) {                        Log.i("onCompleted",movieEntity.toString());                    }                });
如果仔细阅读过上述两篇文章,不难理解这部分代码的含义,由于篇幅原因,这里就不在重复了。

当然如此这般的结合,无法满足对代码有深度洁癖的骚年们。接下来,在此基础上,对代码做整体的封装。

项目目录结构如下:


首先封装网络请求类HTTPHelper.java

    /**     * 这一部分配置常量,可以抽取出常量类     */    private static final String BASE_PATH = "http://www.weather.com.cn/";//访问的地址    private static final long DEFAULT_TIMEOUT = 5000;//默认超时时间(毫秒)    private Retrofit mRetrofit;    private INetService mNetService;    private HTTPHelper(){        OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();        okHttpClient.addInterceptor(new HTTPInterceptor());        okHttpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);        mRetrofit = new Retrofit.Builder()                .client(okHttpClient.build())                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .baseUrl(BASE_PATH)                .build();        mNetService = mRetrofit.create(INetService.class);    }    /**     * 单例控制器     */    private static class SingletonHolder{        private static final HTTPHelper INSTANCE = new HTTPHelper();    }    /**     * 获取单例对象     * @return     */    public static HTTPHelper getInstance(){        return SingletonHolder.INSTANCE;    }
我们需要将网络请求回来的字符串转换成javaBean对象,所以引入Rxjava的map转换机制。代码如下:

    private class HttpResultFunc implements Func1 {        @Override        public T call(IModel iModel) {            if (iModel == null){                try {                    throw new Exception("result model is null");                } catch (Exception e) {                    e.printStackTrace();                }            }            return (T)iModel;        }    }
到此,配置阶段结束,下面将是Rxjava的异步订阅请求网络并返回操作。为了方便Activity、Fragment等界面处理数据,封装Subscriber接口:

package demo.myframework.common;import rx.Subscriber;/** * @Author: lizhipeng * @Data: 16/4/12 下午4:17 * @Description: 自定义调阅者以及结果监听接口 */public class ResultSubscriber extends Subscriber {    private int mRequestType;    private OnResultListener mListener = null;    /**     * 自定义订阅,参数用来区分网络接口,以用来在不同接口操作过程中,处理不同的逻辑     * @param requestType     */    public ResultSubscriber(int requestType) {        this.mRequestType = requestType;        mListener = new OnResultListener() {            @Override            public void onStart(int requestType) {            }            @Override            public void onCompleted(int requestType) {            }            @Override            public void onError(Throwable e, int requestType) {            }            @Override            public void onNext(T t, int requestType) {            }        };    }    @Override    public void onStart() {        mListener.onStart(mRequestType);    }    @Override    public void onCompleted() {        mListener.onCompleted(mRequestType);    }    @Override    public void onError(Throwable e) {        if (e != null){            mListener.onError(e,mRequestType);        }    }    @Override    public void onNext(T t) {        mListener.onNext(t,mRequestType);    }    /**     * 设置订阅监听器     * @param listener     */    public void setOnResultListener(OnResultListener listener){        if (listener != null){            mListener = listener;        }    }    /**     * 订阅的监听器     * @param      */    public interface OnResultListener {        /**         * 网络请求订阅开始         */        void onStart(int requestType);        /**         * 网络请求完成         */        void onCompleted(int requestType);        /**         * 网络请求错误         */        void onError(Throwable e,int requestType);        /**         * 处理请求结果         */        void onNext(T t,int requestType);    }}
已天气访问为例网络请求接口为:

package demo.myframework.interfaces;import demo.myframework.model.WeatherModel;import retrofit2.http.GET;import retrofit2.http.Path;import rx.Observable;/** * @Author: lizhipeng * @Data: 16/4/12 下午2:57 * @Description:  网络请求接口 */public interface INetService {    @GET("data/cityinfo/{city_id}.html")    Observable getWeather(@Path("city_id") String city);}

HTTPHelper.java 中 网络请求数据方法的实现为:

    /**     * 获取网络数据的方法     * @param cityId     */    public void getWeather(String cityId, int resultType, ResultSubscriber.OnResultListener listener){        ResultSubscriber subscriber = new ResultSubscriber<>(resultType);        subscriber.setOnResultListener(listener);        mNetService.getWeather(cityId)                .map(new HttpResultFunc())                .subscribeOn(Schedulers.io())                .unsubscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(subscriber);    }
MainActivity实现OnResultListener接口,点击按钮调用方法为

       HTTPHelper.getInstance().getWeather("101010300",CODE,MainActivity.this);
一下是activity的全部代码:

package demo.myframework.activity;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import demo.myframework.R;import demo.myframework.common.ResultSubscriber;import demo.myframework.http.HTTPHelper;import demo.myframework.model.IModel;import demo.myframework.model.WeatherModel;public class MainActivity extends AppCompatActivity implements ResultSubscriber.OnResultListener{    private static final String TAG = "MainActivity";    private static final int CODE = 1;    private Button mButton;    private TextView mTextView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();    }    private void initData() {        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.i(TAG,"onClick");                HTTPHelper.getInstance().getWeather("101010300",CODE,MainActivity.this);            }        });    }    private void initView() {        mButton = (Button) findViewById(R.id.button);        mTextView = (TextView) findViewById(R.id.textview);    }    private void setResultSubscriber(){    }    /**     * 网络请求前调用,通常显示Progressialog     * @param requestType     */    @Override    public void onStart(int requestType) {        Log.i(TAG,"onStart");    }    /**     * 网络请求完成调用,通常销毁Progressialog     * @param requestType     */    @Override    public void onCompleted(int requestType) {        Log.i(TAG,"onCompleted");    }    /**     * 网络请求错误后调用     * @param e     * @param requestType     */    @Override    public void onError(Throwable e, int requestType) {        Log.i(TAG,"onError");    }    /**     * onNext 方法中处理请求下来的数据     * @param iModel     * @param requestType     */    @Override    public void onNext(IModel iModel, int requestType) {        Log.i(TAG,"onNext");        if (requestType == CODE){            mTextView.setText(((WeatherModel)iModel).getWeatherinfo().toString());        }    }}


另为了方便测试联调,实现OKhttp的过滤接口。一下代码分别为过滤器和javaBean的实现:

HTTPInterceptor.java

package demo.myframework.http;import android.util.Log;import java.io.IOException;import okhttp3.Interceptor;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;/** * @Author: lizhipeng * @Data: 16/4/12 下午5:19 * @Description: 定义http拦截器,用于设置http协议和日志调试 */public class HTTPInterceptor implements Interceptor {    @Override    public Response intercept(Chain chain) throws IOException {        //封装headers        Request request = chain.request().newBuilder()                .addHeader("Content-Type", "application/json") //添加请求头信息                .build();//        Headers headers = request.headers();        String requestUrl = request.url().toString(); //获取请求url地址        String methodStr = request.method(); //获取请求方式        RequestBody body = request.body(); //获取请求body        String bodyStr = (body==null?"":body.toString());        //打印Request数据        Log.i("HTTP-Interceptor","requestUrl=====>"+requestUrl);        Log.i("HTTP-Interceptor","requestMethod=====>"+methodStr);        Log.i("HTTP-Interceptor","requestBody=====>"+body);        Response response = chain.proceed(request);        return response;    }}

WeatherModel.java

package demo.myframework.model;/** * @Author: lizhipeng * @Data: 16/4/12 下午3:16 * @Description:  天气信息模板 */public class WeatherModel implements IModel{    /**     * city : 朝阳     * cityid : 101010300     * temp1 : -2℃     * temp2 : 16℃     * weather : 晴     * img1 : d0.gif     * img2 : n0.gif     * ptime : 18:00     */    private WeatherinfoBean weatherinfo;    public WeatherinfoBean getWeatherinfo() {        return weatherinfo;    }    public void setWeatherinfo(WeatherinfoBean weatherinfo) {        this.weatherinfo = weatherinfo;    }    public static class WeatherinfoBean {        private String city;        private String cityid;        private String temp1;        private String temp2;        private String weather;        private String img1;        private String img2;        private String ptime;        public String getCity() {            return city;        }        public void setCity(String city) {            this.city = city;        }        public String getCityid() {            return cityid;        }        public void setCityid(String cityid) {            this.cityid = cityid;        }        public String getTemp1() {            return temp1;        }        public void setTemp1(String temp1) {            this.temp1 = temp1;        }        public String getTemp2() {            return temp2;        }        public void setTemp2(String temp2) {            this.temp2 = temp2;        }        public String getWeather() {            return weather;        }        public void setWeather(String weather) {            this.weather = weather;        }        public String getImg1() {            return img1;        }        public void setImg1(String img1) {            this.img1 = img1;        }        public String getImg2() {            return img2;        }        public void setImg2(String img2) {            this.img2 = img2;        }        public String getPtime() {            return ptime;        }        public void setPtime(String ptime) {            this.ptime = ptime;        }        @Override        public String toString() {            return "WeatherinfoBean{" +                    "city='" + city + '\'' +                    ", cityid='" + cityid + '\'' +                    ", temp1='" + temp1 + '\'' +                    ", temp2='" + temp2 + '\'' +                    ", weather='" + weather + '\'' +                    ", img1='" + img1 + '\'' +                    ", img2='" + img2 + '\'' +                    ", ptime='" + ptime + '\'' +                    '}';        }    }}
注释已经在代码中详细说明,就不做太多解释了,着重说一点,ResultSubscriber.java中的mRequestType是用来在连续多次请求网络接口时,需要在界面中做不同的处理而区分的属性。使用时,最好也为每个接口配置为对应的唯一值。


附上GitHub地址,https://github.com/QiYuan007/EasyFrame 如果本文对你有帮助,多多start。


如果你有更好的实现方式,请与我联系。















更多相关文章

  1. Android(安卓)8.1 关机充电动画(二)Uboot模式
  2. Android调用Google Map
  3. Android训练课程(Android(安卓)Training) - 使用Volley传输网络
  4. [置顶] Lua 学习教程之android与lua相互调用(二)
  5. android的binder机制研究(C++部分) 分享
  6. Space+onTouchEvent=Hitarea:像Flash那样在Android中扩大点击区域
  7. 关于Android的post,get、cookie网络获取的一些坑
  8. android 自定义View开发实战(四) 圆角矩形ImageView实现
  9. android HAL开发之基于Service的HAL设计

随机推荐

  1. android 将程序设置为app2sd
  2. Android(安卓)中.aar文件生成方法与用法
  3. Android-View-Attribute
  4. ListView setOnItemClickListener无效原
  5. android-RecycleView的导入之旅
  6. Android高手进阶教程(七)之 ----Android(
  7. android 类似QQ 换皮肤 实现思路 apk资源
  8. android:configChanges问题
  9. Android系统底层架构【译】
  10. Android中用Application类实现全局变量