Retrofit+Rxjava 网络请求的完美封装(二)(观察者模式)

上一篇是Retrofit+Rxjava简单封装,是在MainActivity中构建的请求体,这篇博文是将请求体Request也置入到Rxjava中
Retrofit+Rxjava 网络请求的简单封装(一)(观察者模式)

如果想对RxJava进行简单的了解,可以参考我如下的博文
RxJava响应式编程之初级了解

如果相对Retrofit进行简单的了解学习,可以参考我如下的博文
Retrofit简单封装使用–Post请求封装请求体、Get请求通过参数、map方式构建url

我通过公司一个上线App接口来进行Retrofit+Rxjava 的简单学习

http://x-phone.cn/api/v1.0/DeletePrivateContact

当然你直接访问上面的url是无法获取服务器Json数据的,因为是需要封装请求体,如下是在没有封装请求体,返回的错误界面

Method Not Allowed
The method is not allowed for the requested URL.

首先看下请求的Json格式如下

 [getJuheResult]requestJsonStr = 
                                                   {
                                                     "contact_ids": [
                                                       "1475920950100"
                                                     ],
                                                     "godin_id": "4c59396301ab6274bd7892f0b31df36e",
                                                     "imei": "123456789012345",
                                                     "phone_num": "18612185929"
                                                   }

返回的Json格式如下,如下是一种返回的格式:

[getJuheResult.onNext]Head{statuscode='000009', statusmsg='device and user not match'}


这篇博客就对上篇博客的进行Retrofit+Rxjava 简单封装在进行请求体的封装

首先看看上篇博客在MainActivity中封装的HttpRequest请求

ArrayList contact_ids = new ArrayList<>();
contact_ids.add("1475920950100");
HttpRequest httpRequest = new HttpRequest();
httpRequest.setPhone_num("18612185929");
httpRequest.setImei("123456789012345");
httpRequest.setGodin_id("4c59396301ab6274bd7892f0b31df36e");
httpRequest.setContact_ids(contact_ids);

封装之后呢?在上篇博客中,在通过参数传递进来

 public void postClickAppInfoParameterJsonBody(HttpRequest request) {
        if (request == null) {
            throw new NullPointerException("Argument request cannot be null.");
        }
        Log.d(TAG,"[getJuheResult]requestJsonStr = \n"+gson.toJson(jsonParser.parse(gson.toJson(request))));
        FactoryInters.PostClickAppInfoParameterJsonBody server = retrofit.create(FactoryInters.PostClickAppInfoParameterJsonBody.class);
        //观察者
        Subscriber subscriber = new HttpResultSubscriber("getJuheResult");

        server.getJuheResult(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

如上的方式,其实我们可以将它也放到Rxjava中封装起来,通过Rxjava直接传递进来

1、在Rxjava中构建HttpRequest进行传递或者根据业务需要进行转换(当然如果请求业务多了,可以另起一个类统一管理)

   /**
     * 设置线程
     */
    public  Observable setThread(Observable observable) {
        observable.subscribeOn(Schedulers.from(exector))
                .observeOn(AndroidSchedulers.mainThread());
        return observable;
    }

    /**
     * 上传服务器删除联系人操作
     */
    public void postClickAppInfoParameterJsonBody() {
        //被观察者。。。
        RxJavaHelper.getInstance().setThread(Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscribersuper HttpRequest> subscriber) {
                ArrayList contact_ids = new ArrayList<>();
                contact_ids.add("1475920950100");

                HttpRequest httpRequest = new HttpRequest();
                httpRequest.setPhone_num("18612185929");
                httpRequest.setImei("123456789012345");
                httpRequest.setGodin_id("4c59396301ab6274bd7892f0b31df36e");
                httpRequest.setContact_ids(contact_ids);

                subscriber.onNext(httpRequest);
            }
        }))
                .subscribe(new Action1() {
                    @Override
                    public void call(HttpRequest request) {
                        RetrofitManger.getInstance().postClickAppInfoParameterJsonBody(request);
                    }
                });

    }

2、将HttpRequest传递过来之后,就开始进行Retrofit方面的封装首先看基类RetrofitBase

   protected RetrofitBase(){
        retrofit = new Retrofit.Builder()
                .baseUrl(BASEURL)
                .client(client())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }
    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())
                .build();
        return okHttpClient;
    }

3、我们看下Retrofit通过特有的注解方式,配置请求HttpRequest,返回HttpResult的代码接口,跟Rxjava结合起来,然后在第4步操作中,通过Rxjava的观察者模式进行响应操作

public interface FactoryInters {
    //http://x-phone.cn/api/v1.0/DeletePrivateContact
    interface PostClickAppInfoParameterJsonBody{
        @Headers({"Content-Type: application/json","Accept: application/json"})
        @POST("DeletePrivateContact")
        Observable<HttpResult> getJuheResult(@Body HttpRequest request);
    }
}

4、然后看Retrofit主类,主要处理请求返回数据的传递,异步响应操作

    /**
     * {"phone_num": "18612185929", "imei": "123456789012345", "godin_id": "4c59396301ab6274bd7892f0b31df36e", "contact_ids": ["1475920950100"]}
     */
    public void postClickAppInfoParameterJsonBody(HttpRequest request) {
        if (request == null) {
            throw new NullPointerException("Argument request cannot be null.");
        }
        Log.d(TAG,"[getJuheResult]requestJsonStr = \n"+gson.toJson(jsonParser.parse(gson.toJson(request))));
        FactoryInters.PostClickAppInfoParameterJsonBody server = retrofit.create(FactoryInters.PostClickAppInfoParameterJsonBody.class);
        //观察者
        Subscriber subscriber = new HttpResultSubscriber("getJuheResult");

        server.getJuheResult(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }


    private class HttpResultSubscriber extends Subscriber<HttpResult>{

        private String method;

        public HttpResultSubscriber(String methodTag){
            this.method = methodTag;
        }

        @Override
        public void onCompleted() {
            Log.i(TAG, "onCompleted");
        }

        @Override
        public void onError(Throwable e) {
            StringBuffer sb = new StringBuffer();
            sb.append("[").append(method).append(".onError]").append(e);
            Log.e(TAG,sb.toString());
        }

        @Override
        public void onNext(HttpResult httpResult) {

            StringBuffer sb = new StringBuffer();
            sb.append("[").append(method).append(".onNext]")
                    .append(httpResult.getHead().toString());

            Log.i(TAG,sb.toString());
        }
    }

如下的代码,就是Rxjava观察者模式的使用,就是通过传递HttpRequest,获取HttpResult结果,然后在通过构建被观察者,观察者进行事件传递,响应操作和处理

server.getJuheResult(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);

最后再次看下请求体,响应结果如下:

11-03 14:48:23.526 31285-31285/? D/RetrofitManger: [getJuheResult]requestJsonStr = 
                                                   {
                                                     "contact_ids": [
                                                       "1475920950100"
                                                     ],
                                                     "godin_id": "4c59396301ab6274bd7892f0b31df36e",
                                                     "imei": "123456789012345",
                                                     "phone_num": "18612185929"
                                                   }


11-03 14:48:23.758 31285-31285/? I/RetrofitManger: [getJuheResult.onNext]Head{statuscode='000009', statusmsg='device and user not match'}

纠错

   /**
     * 设置线程
     */
    public  Observable setThread(Observable observable) {
        observable.subscribeOn(Schedulers.from(exector))
                .observeOn(AndroidSchedulers.mainThread());
        return observable;
    }

这个经过测试,是运行在主线程的,应该将其拿出来,放到分线程中

———————————————以下是代码区———————————————
配置文件:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.godinsec.db" >

    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>
manifest>

HttpRequest

package com.godinsec.db;

import java.util.ArrayList;

/**
 * 删除联系人封装的请求体
 * {"phone_num": "18612185929", "imei": "123456789012345", "godin_id": "4c59396301ab6274bd7892f0b31df36e", "contact_ids": ["1475920950100"]}
 */
public class HttpRequest {
    private String phone_num;
    private String imei;
    private String godin_id;
    private ArrayList contact_ids;

    public ArrayList getContact_ids() {
        return contact_ids;
    }

    public void setContact_ids(ArrayList contact_ids) {
        this.contact_ids = contact_ids;
    }

    public String getPhone_num() {
        return phone_num;
    }

    public void setPhone_num(String phone_num) {
        this.phone_num = phone_num;
    }

    public String getImei() {
        return imei;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public String getGodin_id() {
        return godin_id;
    }

    public void setGodin_id(String godin_id) {
        this.godin_id = godin_id;
    }

    @Override
    public String toString() {
        return "HttpRequest{" +
                "phone_num='" + phone_num + '\'' +
                ", imei='" + imei + '\'' +
                ", godin_id='" + godin_id + '\'' +
                ", contact_ids=" + contact_ids +
                '}';
    }
}

HttpResult

package com.godinsec.db;

import java.util.ArrayList;

/**
 * 删除正确返回的json格式
 * {"head": {
 * "statuscode": "000000",
 * "statusmsg": "success"
 * }
 * }
 */
public class HttpResult {

    @Override
    public String toString() {
        return "HttpResult{" +
                "head=" + head +
                '}';
    }

    private Head head;

    public Head getHead() {
        return head;
    }

    public void setHead(Head head) {
        this.head = head;
    }


    public static class Head {
        private String statuscode;
        private String statusmsg;

        public String getStatuscode() {
            return statuscode;
        }

        public void setStatuscode(String statuscode) {
            this.statuscode = statuscode;
        }

        public String getStatusmsg() {
            return statusmsg;
        }

        public void setStatusmsg(String statusmsg) {
            this.statusmsg = statusmsg;
        }

        @Override
        public String toString() {
            return "Head{" +
                    "statuscode='" + statuscode + '\'' +
                    ", statusmsg='" + statusmsg + '\'' +
                    '}';
        }
    }

}

RxJavaHelper

package com.godinsec.db;


import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by Safly on 2016/11/3.
 */

public final class RxJavaHelper {
    private ExecutorService exector = null;

    private RxJavaHelper() {
        exector = Executors.newFixedThreadPool(5, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                AtomicInteger mCount = new AtomicInteger(1);
                Thread thread = new Thread(r, "PrivacyLauncherThread_id:" + mCount.getAndIncrement());
                thread.setPriority(Thread.NORM_PRIORITY - 1);
                return thread;
            }
        });
    }

    private static final class Factory {
        private static final RxJavaHelper instance = new RxJavaHelper();
    }

    public static RxJavaHelper getInstance() {
        return Factory.instance;
    }

    /**
     * 设置线程
     */
    public  Observable setThread(Observable observable) {
        observable.subscribeOn(Schedulers.from(exector))
                .observeOn(AndroidSchedulers.mainThread());
        return observable;
    }

    /**
     * 上传服务器删除联系人操作
     */
    public void postClickAppInfoParameterJsonBody() {
        //被观察者。。。
        RxJavaHelper.getInstance().setThread(Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscribersuper HttpRequest> subscriber) {
                ArrayList contact_ids = new ArrayList<>();
                contact_ids.add("1475920950100");

                HttpRequest httpRequest = new HttpRequest();
                httpRequest.setPhone_num("18612185929");
                httpRequest.setImei("123456789012345");
                httpRequest.setGodin_id("4c59396301ab6274bd7892f0b31df36e");
                httpRequest.setContact_ids(contact_ids);

                subscriber.onNext(httpRequest);
            }
        }))
                .subscribe(new Action1() {
                    @Override
                    public void call(HttpRequest request) {
                        RetrofitManger.getInstance().postClickAppInfoParameterJsonBody(request);
                    }
                });

    }
}

RetrofitBase

package com.godinsec.db;


import com.godinsec.db.RxJavaHelper;

import org.apache.http.conn.ssl.AllowAllHostnameVerifier;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Seeker on 2016/9/13.
 */

public abstract class RetrofitBase {

//    private static final String BASEURL = "http://10.0.5.97:9000/api/v1.0/";

    private static final String BASEURL = "http://x-phone.cn/api/v1.0/";

    private static final long TIMEOUT = 5 * 1000;

    protected Retrofit retrofit;

    protected RetrofitBase(){
        retrofit = new Retrofit.Builder()
                .baseUrl(BASEURL)
                .client(client())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }

    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())
                .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];
        }
    }

}

RetrofitManger

package com.godinsec.db;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;

import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * {"resultcode":"101","reason":"错误的请求KEY!","result":null,"error_code":10001}
 */

public class RetrofitManger extends RetrofitBase {

    private static final String TAG = "RetrofitManger";

    private Gson gson;

    private JsonParser jsonParser;

    private RetrofitManger() {
        super();
        gson = new GsonBuilder().setPrettyPrinting().create();
        jsonParser = new JsonParser();
    }

    private static final class Factory {
        private static final RetrofitManger instance = new RetrofitManger();
    }

    public static RetrofitManger getInstance() {
        return Factory.instance;
    }


    /**
     * {"phone_num": "18612185929", "imei": "123456789012345", "godin_id": "4c59396301ab6274bd7892f0b31df36e", "contact_ids": ["1475920950100"]}
     */
    public void postClickAppInfoParameterJsonBody(HttpRequest request) {
        if (request == null) {
            throw new NullPointerException("Argument request cannot be null.");
        }
        Log.d(TAG,"[getJuheResult]requestJsonStr = \n"+gson.toJson(jsonParser.parse(gson.toJson(request))));
        FactoryInters.PostClickAppInfoParameterJsonBody server = retrofit.create(FactoryInters.PostClickAppInfoParameterJsonBody.class);
        //观察者
        Subscriber subscriber = new HttpResultSubscriber("getJuheResult");

        server.getJuheResult(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }


    private class HttpResultSubscriber extends Subscriber<HttpResult>{

        private String method;

        public HttpResultSubscriber(String methodTag){
            this.method = methodTag;
        }

        @Override
        public void onCompleted() {
            Log.i(TAG, "onCompleted");
        }

        @Override
        public void onError(Throwable e) {
            StringBuffer sb = new StringBuffer();
            sb.append("[").append(method).append(".onError]").append(e);
            Log.e(TAG,sb.toString());
        }

        @Override
        public void onNext(HttpResult httpResult) {

            StringBuffer sb = new StringBuffer();
            sb.append("[").append(method).append(".onNext]")
                    .append(httpResult.getHead().toString());

            Log.i(TAG,sb.toString());
        }
    }
}

FactoryInters

package com.godinsec.db;

import java.util.Map;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import rx.Observable;

public interface FactoryInters {
    //http://x-phone.cn/api/v1.0/DeletePrivateContact
    interface PostClickAppInfoParameterJsonBody{
        @Headers({"Content-Type: application/json","Accept: application/json"})
        @POST("DeletePrivateContact")
        Observable getJuheResult(@Body HttpRequest request);
    }
}

MainActivity

package com.godinsec.db;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RxJavaHelper.getInstance().postClickAppInfoParameterJsonBody();

    }
}

你可能感兴趣的:(Android网络操作,Android网络操作)