安卓进阶之 封装自己的网络请求工具

此处以retrofit 为例:方便创建新项目的时候,不用拷贝太多东西。

 首先第一步:

可以创建一个工具类的项目,然后创建一个library。步骤如上所示。这样的话方便测试,自己的工具类封装是否成功,也方便在创建新项目的时候,可以直接在新项目中创建一个与我们工具类中的library 相同名字的 library,例如我的项目中,为了方便以后library的拷贝方便,我会都创建为 mylibrary.

第二步:封装自己的网络请求框架。此处以我的项目中的retrofit 为例子。

1.引入依赖。

/** 网络请求的封装      */
implementation 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit
implementation 'com.google.code.gson:gson:2.6.2'//Gson 库
//下面两个是RxJava 和RxAndroid 添加这两个依赖 可以直接使用rxbus
implementation 'io.reactivex:rxjava:1.1.0'
implementation 'io.reactivex:rxandroid:1.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
//转换器,请求结果转换成Model
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
//配合Rxjava 使用
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
implementation 'com.squareup.okhttp3:okhttp:3.4.1'

 2.封装相关的类。

 

 其中一个关键的点 就是,将我们最终调用 的httpmanager 这个类 ,写到我们的APP包下,方便我们跟随不同项目,不同的需求进行修改。灵活使用。

其中,httpmanager中调用的工具类,需要在我们的library中封装完成,因为这些类,不会因为业务的变化而变化,或者说变化比较小。

3.retrofit的优点是比较优雅,此处举例演示,如何使用library中的工具类,创建APP包下的请求manager。

package com.example.administrator.mytestretrofit.http;

import android.util.Log;

import com.example.mylibrary.app.Constants;
import com.example.administrator.mytestretrofit.http.remote.RemoteService;
import com.example.mylibrary.http.engine.ExceptionEngine;
import com.example.mylibrary.http.engine.RetryWhenNetworkException;
import com.example.mylibrary.http.gson.IJson;
import com.example.mylibrary.http.interceptor.MoreBaseUrlInterceptor;
import com.example.mylibrary.http.subscriber.ProgressSubscriber;
import com.example.mylibrary.utils.log.LogUtils;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * http交互处理类
 */
public class HttpManager {

    public static final String TAG = "HttpManager-------";

    /*超时设置*/
    private static final int DEFAULT_TIMEOUT = 6;
    private RemoteService httpService;
    private volatile static HttpManager INSTANCE;

    //构造方法私有
    private HttpManager() {

        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                LogUtils.d(TAG,message);
            }
        });
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
                .connectTimeout(5, TimeUnit.SECONDS)  //设置超时时间 10s
                .readTimeout(5, TimeUnit.SECONDS)     //设置读取超时时间
                .writeTimeout(5, TimeUnit.SECONDS)   //设置写入超时时间
                .addInterceptor(httpLoggingInterceptor)//添加一个拦截器
                .addInterceptor(new MoreBaseUrlInterceptor());

        OkHttpClient okClient = builder.build();

        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(IJson.gson)) // 使用Gson作为数据转换器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器
                .client(okClient)
                .baseUrl(Constants.Base.BASE_URL_RELEASE)//获取 最终的base url
                /*.baseUrl(App.getInstance().getRealUrl())//此处选择 api 的真实网址*/
                .build();
        httpService = retrofit.create(RemoteService.class);
    }

    //获取单例
    public static HttpManager getInstance() {
        if (INSTANCE == null) {
            synchronized (HttpManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new HttpManager();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 处理http请求
     *
     * @param basePar 封装的请求数据
     */
    public void doHttpDeal(BaseEntity basePar) {
        //if (basePar.isShowProgress())
        ProgressSubscriber subscriber = new ProgressSubscriber(basePar.getListener()
                , basePar.getContext()
                , basePar.isShowProgress()
                , basePar.isCancel()
                , basePar.isShowError()
                , basePar.getMsg());
        basePar.getObservable(httpService)
                /*失败后的retry配置*/
                .retryWhen(new RetryWhenNetworkException())
                /*生命周期管理*/
                .compose(basePar.getTransformer())
//                .map(new_icon ServerResponseFunc<String>())//拦截服务器返回的错误
                .onErrorResumeNext(new HttpResponseFunc<String>()) //HttpResultFunc()为拦截onError事件的拦截器
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread())
                /*结果判断*/
//                .map(basePar)
                .subscribe(subscriber);
    }

    private class HttpResponseFunc<T> implements Func1<Throwable, Observable<T>> {
        @Override
        public Observable<T> call(Throwable throwable) {
            Log.e(TAG,"----这是啥异常?--");
            throwable.printStackTrace();
            return Observable.error(ExceptionEngine.handleException(throwable)); //ExceptionEngine为处理异常的驱动器
        }
    }

}

 大家可以看一下 ,这个是我封装的请求调用类,关注点可以放到 import上面。

其实这个类里面,大部分也是 一些不用变化的内容,只是关键在 RemoteService 这个类里面。

public interface RemoteService {

    /**
     * 登录请求token
     */
    @Headers("urlname:common_base_url_header")
    @POST("action/LoginAction/mobileNumberLogin")
    Observable<Response<BaseHttpEntity<LoginForAccessTokenEntity>>> loginForToken(
            @Body FormBody body
    );


    /**
     * 根据token请求jssionid
     */
    @Headers("urlname:common_base_url_header")
    @POST("action/LoginAction/csLogin")
    Observable<Response<BaseHttpEntity<UserInfoEntity>>> loginFromTokenToJssionId(
            @Body FormBody body
    );

    /**
     * 发送验证码接口
     * mobileNumber:11位手机号
     * type:验证码类型 0注册 1重置密码 2修改手机号 3修改支付密码
     */
    @Headers("urlname:common_base_url_header")
    @POST("action/LoginAction/sendSMSCode")
    Observable<Response<BaseHttpEntity<SendSMSCodeEntity>>> getSendSMSCode(
            @Body FormBody body
    );
}

这个类是需要根据我们的业务进行变动的,为了方便我们的一个项目中,会创建多个module,所以,将httpmanager 分别放在module中是比较方便的。

3.接下来就行请求的接口api ,与返回的数据entity。

举例演示:

 这些网络请求的接口api,与返回的数据类 根据自己的后台返回的数据,灵活的创建,这里不多做赘述。

 4.在module中的调用举例:

亲测有效。大家也可以尝试一下,封装一个数据自己的工具项目。 或许大家都已经有了属于自己的工具项目,就是我落后一步啦。哈哈

猜你喜欢

转载自blog.csdn.net/weixin_37166398/article/details/91796123