Android网络编程Retrofit+Rxjava用法详解

一.简介

Retrofit是是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,大量的app都采用OkHttp做网络请求,其源码详见OkHttp Github


二.贴代码

1.首先在gradle中添加如下配置

    compile 'com.google.code.gson:gson:2.6.2'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
这样就将Retrofit+RxJava引入进来了

2.在manifest中添加网络权限

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

3.写个接口FactoryInters,用来封装get post方法

①这是get方法,一会在RetrofitBase中调用

    @GET
    Observable<JSONObject> getData(
            @Url String url,
            @QueryMap Map<String, Object> params);

②这是post方法,一会在RetrofitBase中调用

    @FormUrlEncoded
    @POST
    Observable<JSONObject> postData(
            @Url String url,
            @FieldMap Map<String, Object> params);
③这是上传文件的方法

有两种写法:使用@MultiPart注解,@Part注解文件入参,则文件入参类型应是List< okhttp3.MultipartBody.Part>;

                        不使用@Multipart注解,直接使用@Body注解文件入参,则文件入参类型应是okhttp3.MultipartBody

    @Multipart
    @POST
    Observable<JSONObject> uploadFiles(
            @Url String url,
            @PartMap() Map<String, RequestBody> strParams,
            @Part() List<MultipartBody.Part> fileParams);

4.新建类RetrofitBase,用来具体实现get post方法

全局参数:

    private static final String TAG = RetrofitBase.class.getSimpleName();
    protected static String BASEURL = Config.SERVER_ADDRESS;
    private static final long TIMEOUT = 5 * 1000;
    private FactoryInters service;
    private Retrofit retrofit;
    private Gson gson;
    private JsonParser jsonParser;

 初始化 
 

   private RetrofitBase() {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASEURL)
                .client(client())
                        //增加返回值为Gson的支持(自定义MyGsonConverterFactory)
                .addConverterFactory(MyGsonConverterFactory.create())
                        //增加返回值为Oservable<T>的支持
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        service = retrofit.create(FactoryInters.class);
        gson = new GsonBuilder().setPrettyPrinting().create();
        jsonParser = new JsonParser();
    }
   private static class SingletonHolder {
        private static final RetrofitBase INSTENCE = new RetrofitBase();
    }

    public static RetrofitBase getInstance() {
        return SingletonHolder.INSTENCE;
    }
获得连接
   private OkHttpClient client() {

        LauncherTrust launcherTrust = new LauncherTrust();

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .sslSocketFactory(sslSocketFactory(launcherTrust), launcherTrust)
                .hostnameVerifier(new AllowAllHostnameVerifier())
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(false)//失败重连
                .build();
        return okHttpClient;
    }

    private SSLSocketFactory sslSocketFactory(LauncherTrust launcherTrust) {

        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{launcherTrust}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }

    static class LauncherTrust implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    LogInterceptor interceptor = new LogInterceptor(new LogInterceptor.Logger() {
        @Override
        public void log(String message) {
            Log.i(TAG, message);
        }
    });

重点!!!

get方法

   public void getData(String url, Map<String, Object> params, SubListenerHelper listener) {
        Log.d(TAG, "[get请求参数] = \n" + gson.toJson(jsonParser.parse(gson.toJson(params))));
        service.getData(url, params)
                .compose(schedulersTransformer())
                .subscribe(listener);
    }
post方法
  public void postData(String url, Map<String, Object> params, SubListenerHelper listener) {
        Log.d(TAG, "[post请求参数] = \n" + gson.toJson(jsonParser.parse(gson.toJson(params))));
        service.postData(url, params)
                .compose(schedulersTransformer())
                .subscribe(listener);
    }

上传文件

   public void uploadFiles(String url, Map<String, RequestBody> strParams, List<MultipartBody.Part> fileParams, SubListenerHelper subscriberHelper) {
        service.uploadFiles(url, strParams, fileParams)
                .compose(schedulersTransformer())
                .subscribe(subscriberHelper);
    }

Observable

   Observable.Transformer schedulersTransformer() {
        return new Observable.Transformer() {


            @Override
            public Object call(Object observable) {
                return ((Observable) observable)
                        .subscribeOn(Schedulers.io())//执行在io线程
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());//主线程显示
            }
        };
    }

上传文件时将map转成List

   public static List<MultipartBody.Part> fileList2PartList(Map<String, File> fileMap) {
        List<MultipartBody.Part> partList = new ArrayList<>(fileMap.size());
        for (Map.Entry<String, File> entry : fileMap.entrySet()) {
            String fileKey = entry.getKey();
            File file = entry.getValue();
            RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
            MultipartBody.Part part = MultipartBody.Part.createFormData(fileKey, file.getName(), requestBody);
            partList.add(part);
        }
        return partList;
    }

4.LogInterceptor类

   public class LogInterceptor implements Interceptor {
    private static final Charset UTF8 = Charset.forName("UTF-8");

    public enum Level {
        NONE,
        BASIC,
        HEADERS,
        BODY
    }

    public interface Logger {
        void log(String message);

        int INFO = 800;
        Logger DEFAULT = new Logger() {
            @Override
            public void log(String message) {
                Platform.get().log(INFO, message, null);
            }
        };
    }

    public LogInterceptor() {
        this(Logger.DEFAULT);
    }

    public LogInterceptor(Logger logger) {
        this.logger = logger;
    }

    private final Logger logger;

    private volatile Level level = Level.BODY;

    /**
     * Change the level at which this interceptor logs.
     */
    public LogInterceptor setLevel(Level level) {
        if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead.");
        this.level = level;
        return this;
    }

    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Level level = this.level;

        Request request = chain.request();
        if (level == Level.NONE) {
            return chain.proceed(request);
        }

        boolean logBody = level == Level.BODY;
        boolean logHeaders = logBody || level == Level.HEADERS;

        RequestBody requestBody = request.body();
        boolean hasRequestBody = requestBody != null;

        String requestStartMessage = request.method() + ' ' + request.url();
        if (!logHeaders && hasRequestBody) {
            requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
        }
        logger.log(requestStartMessage);

        if (logHeaders) {

            if (!logBody || !hasRequestBody) {
                logger.log("--> END " + request.method());
            } else if (bodyEncoded(request.headers())) {
                logger.log("--> END " + request.method() + " (encoded body omitted)");
            } else if (request.body() instanceof MultipartBody) {
                //如果是MultipartBody,会log出一大推乱码的东东
            } else {
                Buffer buffer = new Buffer();
                requestBody.writeTo(buffer);

                Charset charset = UTF8;
                MediaType contentType = requestBody.contentType();
                if (contentType != null) {
                    contentType.charset(UTF8);
                }

                logger.log(buffer.readString(charset));

//                logger.log(request.method() + " (" + requestBody.contentLength() + "-byte body)");
            }
        }

        long startNs = System.nanoTime();
        Response response = chain.proceed(request);
        long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
        logger.log(response.code() + ' ' + response.message() + " (" + tookMs + "ms" + ')');

        return response;
    }

    private boolean bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }

    private static String protocol(Protocol protocol) {
        return protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1";
    }
}

5.MyGsonConverterFactory类

   public class MyGsonConverterFactory extends Converter.Factory {

    private static final String TAG = MyGsonConverterFactory.class.getSimpleName();
    private final Gson gson;

    public static MyGsonConverterFactory create() {
        return create(new Gson());
    }

    public static MyGsonConverterFactory create(Gson gson) {
        return new MyGsonConverterFactory(gson);

    }


    private MyGsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }

    /**
     * 响应
     *
     * @param type
     * @param annotations
     * @param retrofit
     * @return
     */
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        Log.i(TAG, "responseBodyConverter");
        return new JsonResponseBodyConverter(gson, adapter);
    }

    /**
     * 请求
     *
     * @param type
     * @param parameterAnnotations
     * @param methodAnnotations
     * @param retrofit
     * @return
     */
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        Log.i(TAG, "requestBodyConverter");
        return new JsonRequestBodyConverter<>(gson, adapter); //请求
    }
}

6.自定义请求类:JsonRequestBodyConverter

   public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final String TAG = JsonRequestBodyConverter.class.getSimpleName();
    private Gson gson;
    private TypeAdapter<T> adapter;

    public JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }

    @Override
    public RequestBody convert(T value) throws IOException {
        Log.i(TAG, "convert(T value)");
        String result = URLEncoder.encode(EncryptUtil.encryptByPublicKey(value.toString()), "utf-8");
        String postBody = gson.toJson(result); //对象转化成json
        Log.i(TAG, "转化后的数据:" + postBody);
        return RequestBody.create(MEDIA_TYPE, postBody);
    }
}

7.自定义响应类:JsonResponseBodyConverter

   public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {

    private static final String TAG = JsonResponseBodyConverter.class.getSimpleName();
    private final Gson mGson;//gson对象
    private final TypeAdapter<JSONObject> adapter;

    public JsonResponseBodyConverter(Gson gson, TypeAdapter<JSONObject> adapter) {
        this.mGson = gson;
        this.adapter = adapter;
    }


    @Override
    public T convert(ResponseBody responseBody) throws IOException {
        Log.i(TAG, "ResponseBody");
        String responseString = responseBody.string();
        String result = EncryptUtil.decryptByPublicKey(responseString);//解密
        Log.i(TAG, "解密的服务器数据:" + result);

        JSONObject data = null;
        try {
            data = new JSONObject(result);
        } catch (JSONException e) {
            Log.i(TAG, "e:" + e);
            e.printStackTrace();
        }
        return (T) data;
    }
}

8.封装的解析类SubListenerHelper

   public abstract class SubListenerHelper extends Subscriber<JSONObject> {

    private static final String TAG = SubListenerHelper.class.getSimpleName();
    private boolean toastInfo = false;

    public abstract void onSuccess(JSONObject oriData, ServerResponse response);

    public abstract void onFailure(Throwable e);

    public abstract void onFinish();

    @Override
    public void onNext(JSONObject data) {
        ServerResponse response = ServerResponse.parseFromVolleyResponse(data);
        Log.i(TAG, "onNext data=" + data);
        //提示信息
        if (!response.isSuccess) {
            if (toastInfo) {
                //如果服务器返回的status状态不为1,就弹出服务器给的吐司
                if (!TextUtils.isEmpty(response.msg)) {
                    Toast.makeText(AppContext.getContext(), response.msg, Toast.LENGTH_SHORT).show();
                } else if (!TextUtils.isEmpty(response.error)) {
                    Toast.makeText(AppContext.getContext(), response.error, Toast.LENGTH_SHORT).show();
                }
            }

        }
        if (null != response) {
            onSuccess(data, response);
        }
    }

    @Override
    public void onError(Throwable e) {
        Log.i(TAG, "onError e=" + e);
        onFailure(e);
    }

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

    public SubListenerHelper setToastInfo(boolean toastInfo) {
        this.toastInfo = toastInfo;
        return this;
    }
}

9.ServerResponse类

解析统一的格式

{"error":"E00000000","msg":"成功(没有异常)","status":"1"}

这是我的返回格式,不同格式可根据需求改代码

    public class ServerResponse {

    public static final int STATUS_SUCCESS = 1;
    public boolean isSuccess;

    public JSONObject data;
    public String error;
    public String msg;
    public int status;

    //对网络返回的json数据进行解析
    public static ServerResponse parseFromVolleyResponse(JSONObject object) {
        ServerResponse result = new ServerResponse();
        if (object != null) {
            result.status = object.optInt("status");
            result.isSuccess = result.status == STATUS_SUCCESS;
            result.error = object.optString("error");
            result.msg = object.optString("msg");
            //如果是数据就不能用result.data----object
            result.data = object.optJSONObject("data");
        }
        return result;
    }

    @Override
    public String toString() {
        return "ServerResponse{" +
                "data=" + data +
                ", error='" + error + '\'' +
                ", msg='" + msg + '\'' +
                ", status=" + status +
                '}';
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_33634330/article/details/77746062