【Android】Jetpack全组件实战开发短视频应用App(五)

前言

项目地址
这一篇我们主要是网络库的封装,这里我们使用的是OkHttp,做一些简单额Get,Post封装,之后到了Room那里我们再加上缓存

我们首先添加依赖

	//okhttp
	implementation 'com.squareup.okhttp3:okhttp:4.2.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
    //room
    implementation "android.arch.persistence.room:runtime:1.1.1"
    implementation "android.arch.lifecycle:extensions:1.1.1"
    annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
    annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
    //解析json
    implementation 'com.alibaba:fastjson:1.2.59'

接着我们新建一个ApiService类,用于初始化我们网络库

public class ApiService {
    protected static final OkHttpClient OK_HTTP_CLIENT;

    static {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OK_HTTP_CLIENT = new OkHttpClient.Builder()
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .connectTimeout(30, TimeUnit.SECONDS)
                .addInterceptor(loggingInterceptor)
                .build();

        TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

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

        try {
            SSLContext ssl = SSLContext.getInstance("SSL");
            ssl.init(null,trustManagers,new SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }

    }
}

里面就是初始化OkHttp和一些网络相关的东西,接下我们编写Request类,请求一般都会有请求地址,请求头和请求参数,所以我们定义三个变量,同时加上相应方法

public abstract class Request<T, R extends Request> {
    protected String mUrl;
    protected HashMap<String, String> mHeaders = new HashMap<>();
    protected HashMap<String, Object> mParams = new HashMap<>();
 public Request(String url) {
        mUrl = url;
    }

    public R addHeader(String key, String value) {
        mHeaders.put(key, value);
        return (R) this;
    }

    public R addParam(String key, Object value) {
        if (value == null) {
            return (R) this;
        }
        //int byte char short long double float boolean 和他们的包装类型,但是除了 String.class 所以要额外判断
        try {
            if (value.getClass() == String.class) {
                mParams.put(key, value);
            } else {
                Field field = value.getClass().getField("TYPE");
                Class claz = (Class) field.get(null);
                if (claz.isPrimitive()) {
                    mParams.put(key, value);
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return (R) this;
    }
}

这里解释下addParam那个方法中有个判断是否是基本类型的校验,这块可以使用if/else实现,也可以通过反射实现,我们首先随便打开一个基本类型的包装类Integer
【Android】Jetpack全组件实战开发短视频应用App(五)_第1张图片
每个基本类型都有这个TYPE,我们通过反射拿到变量,然后通过这个变量拿到对应的Class,Class类中有个方法可以判断是不是基本类型
【Android】Jetpack全组件实战开发短视频应用App(五)_第2张图片
这样就省去了一堆if/else判断

OK,请求分同步和异步,这里我们就都用一个方法execute,根据入参是否有CallBack来判断是同步还是异步,我们先写个Callback

public abstract class JsonCallback<T> {
    public void onSuccess(ApiResponse<T> response) {

    }

    public void onError(ApiResponse<T> response) {

    }

    public void onCacheSuccess(ApiResponse<T> response) {

    }
}

我们还要根据Get请求还是Post请求来生成不能的Request,所以我们在我们的Request这个抽象类中写一个抽象方法提供给子类实现

    protected abstract okhttp3.Request generateRequest(okhttp3.Request.Builder builder);

public class GetRequest<T> extends Request<T, GetRequest> {
    public GetRequest(String url) {
        super(url);
    }

    @Override
    protected okhttp3.Request generateRequest(okhttp3.Request.Builder builder) {
        //get 请求把参数拼接在 url后面
        String url = UrlCreator.createUrlFromParams(mUrl, mParams);
        return builder.get().url(url).build();
    }
}

Get请求是把参数拼接在url后面,这里咱们直接创建一个工具类使用

public class UrlCreator {

    public static String createUrlFromParams(String url, Map<String, Object> params) {
        StringBuilder builder = new StringBuilder();
        builder.append(url);
        if (url.contains("?") || url.contains("&")) {
            builder.append("&");
        }else {
            builder.append("?");
        }

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            try {
                String value = URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8");
                builder.append(entry.getKey()).append("=").append(value).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        builder.deleteCharAt(builder.length() - 1);

        return builder.toString();
    }
}

接着是PostRequest的实现

public class PostRequest<T> extends Request<T, PostRequest> {
    public PostRequest(String url) {
        super(url);
    }

    @Override
    protected okhttp3.Request generateRequest(okhttp3.Request.Builder builder) {
        //post请求表单提交
        FormBody.Builder bodyBuilder = new FormBody.Builder();
        for (Map.Entry<String, Object> entry : mParams.entrySet()) {
            bodyBuilder.add(entry.getKey(), String.valueOf(entry.getValue()));
        }
        return builder.url(mUrl).post(bodyBuilder.build()).build();
    }
}

然后我们继续回到我们的Request类中,我们一般项目中返回的信息都是有固定格式的,外层基本上都是一样的,我们只需要里面data或者result的东西,所以我们写一个ApiResponse类,

public class ApiResponse<T> {
    public boolean success;
    public int status;
    public String message;
    public T body;
}

这样的话我们就可以通过fastjson把我们网络请求参数值解析成我们想要的样式,这里需要一个convert方法,所以我们还需要编写一个工具类

public interface Convert<T> {
    T convert(String response, Type type);
}
public class JsonConvert implements Convert {
    //默认的Json转 Java Bean的转换器
    @Override
    public Object convert(String response, Type type) {
        JSONObject jsonObject = JSON.parseObject(response);
        JSONObject data = jsonObject.getJSONObject("data");
        if (data != null) {
            Object data1 = data.get("data");
            return JSON.parseObject(data1.toString(), type);
        }
        return null;
    }
}

这样我们就可以在Request类中完成我们剩下的同步和异步方法了

    public ApiResponse<T> execute() {
        if (mType == null) {
            throw new RuntimeException("同步方法,response 返回值 类型必须设置");
        }
        ApiResponse<T> result = null;
        try {
            Response response = getCall().execute();
            result = parseResponse(response, null);
        } catch (IOException e) {
            e.printStackTrace();
            result = new ApiResponse<>();
            result.message = e.getMessage();
        }
        return result;
    }

    public void execute(final JsonCallback callback) {
        getCall().enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                ApiResponse<T> apiResponse = new ApiResponse<>();
                apiResponse.message = e.getMessage();
                callback.onError(apiResponse);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ApiResponse<T> apiResponse = parseResponse(response,callback);
                if (!apiResponse.success) {
                    callback.onError(apiResponse);
                }else {
                    callback.onSuccess(apiResponse);
                }
            }
        });
    }

    private Call getCall() {
        okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
        addHeaders(builder);
        okhttp3.Request request = generateRequest(builder);
        return ApiService.OK_HTTP_CLIENT.newCall(request);
    }

    private void addHeaders(okhttp3.Request.Builder builder) {
        for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue());
        }
    }

    private ApiResponse<T> parseResponse(Response response, JsonCallback callback) {
        String message = null;
        int status = response.code();
        boolean success = response.isSuccessful();
        ApiResponse<T> result = new ApiResponse<>();
        Convert convert = ApiService.sConvert;
        try {
            String content = response.body().string();
            if (success) {
                if (callback != null) {
                    ParameterizedType type = (ParameterizedType) callback.getClass().getGenericSuperclass();
                    Type argument = type.getActualTypeArguments()[0];
                    result.body = (T) convert.convert(content, argument);
                } else if (mType != null) {
                    result.body = (T) convert.convert(content, mType);
                }
                else {
                    Log.e("request", "parseResponse: 无法解析 ");
                }
            } else {
                message = content;
            }
        } catch (Exception e) {
            message = e.getMessage();
            success = false;
            status = 0;
        }
        result.success = success;
        result.status = status;
        result.message = message;

        return result;
    }

同时我们在ApiService中添加几个方法

 public static void init(String baseUrl, Convert convert) {
        sBaseUrl = baseUrl;
        if (convert == null) {
            convert = new JsonConvert();
        }
        sConvert = convert;
    }

    public static <T> GetRequest<T> get(String url) {
        return new GetRequest<>(sBaseUrl + url);
    }

    public static <T> PostRequest<T> post(String url) {
        return new PostRequest<>(sBaseUrl + url);
    }

到此基础的网络请求就封装完了,后续会添加缓存

你可能感兴趣的:(Jetpack)