Android 架构之隔离层设计(实现一键切换主流网络框架) 上

1,318 阅读5分钟

前言

本篇文章主要讲解 Android 比较常用的网络框架封装,以及实现一句代码随意切换主流网络框架。读者也可根据该本章思路实现其他效果,比如说,随意切换权限请求框架等。

特点

按这思路写,代码重构非常简单!

什么是隔离层设计?

先来个图解释下 隔离层设计图解

我们就拿现实生活举例。

  • 将买房的人(客户)看成是我们写的APP;

  • 将有房的人(业主)看成是我们接触的主流网络框架(XUtils、OkHttp、OkGo....);

  • 将房地产公司(比如说链家)看成是客户(我们app)所需要的服务(post、get网络请求等);

  • 将业务员(中介)看成是客户的推荐者;

那么

App想要实现网络请求,就要先去找到房产公司的业务员,业务员就会在房产公司里拿到已经入驻的网络框架列表(业主列表),提供给用户选择,用户不满意这个房子(网络框架),就可以随时换下一个。而房产公司以及业务员就是本章所谓的隔离层

思路理解清楚了,接下来就开始实战操作了

第一步,我们先创建房产公司 IHttpProcessor

/**
 * 房产公司
 */
public interface IHttpProcessor {
    //有卖房的能力
    //网络访问的能力
    void post(String url, Map<String,Object> params, ICallback callback);
    void get(String url, Map<String,Object> params,ICallback callback);
}

交易是否成功的回调 ICallback

/**
 * 顶层的回调接口
 */
public interface ICallback {
    void onSuccess(String result);
    void onFailure(String e);
}

以及 ICallback 扩展,HttpCallback


/**
 * 回调接口的一种实现
 */
public abstract class HttpCallback<Result> implements ICallback{
    @Override
    public void onSuccess(String result) {
        //网络上回来的结果都 在result上
        //1.得到调用者用什么样的javaBean来接收数据
        Class<?> clz=analysisClassInfo(this);
        //2.把String转成javaBean对象交给用户
        Gson gson=new Gson();
        Result objResult=(Result)gson.fromJson(result,clz);
        //3.把结果交给用户
        onSuccess(objResult);
    }

    public abstract void onSuccess(Result objResult);

    /**
     * 通过该功能得到输入参数的实际类型
     */
    private Class<?> analysisClassInfo(Object object){
        //getGenericSuperclass()返回一个类型 对象
        //这个对象可以得到包含原始类型,参数化,数组,类型变量,基本数据类型
        Type getType=object.getClass().getGenericSuperclass();
        Type[] params=((ParameterizedType)getType).getActualTypeArguments();
        return (Class<?>)params[0];
    }

    @Override
    public void onFailure(String e) {

    }
}

代码分析:为什么要创建该类?想象一下,当用户,买房成功时,客户是不是要有合同,以及各种凭证。而该类就是对网络请求成功后的数据做了一层数据解析,尽量把复杂的数据处理好,给上一层递交一个非常简易的数据结构。

第二步,我们创建业主,并入驻房产公司(OkHttp举例)


public class OkHttpProcessor implements IHttpProcessor {

    private OkHttpClient mOkHttpClient;
    private Handler myHandler;

    public OkHttpProcessor(){
        mOkHttpClient=new OkHttpClient();
        myHandler=new Handler(Looper.getMainLooper());
    }

    @Override
    public void post(String url, Map<String, Object> params,final ICallback callback) {
        final RequestBody requestBody=appendBody(params);
        Request request=new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String result=response.body().string();
                if(response.isSuccessful()){
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(result);
                        }
                    });
                }else{
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onFailure(result);
                        }
                    });
                }
            }
            @Override
            public void onFailure(Call call, IOException e) {
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure("onFailure");
                    }
                });
            }

        });
    }

    @Override
    public void get(String url, Map<String, Object> params, ICallback callback) {

    }

    private RequestBody appendBody(Map<String, Object> params){
        FormBody.Builder body=new FormBody.Builder();
        if(params==null || params.isEmpty()){
            return body.build();
        }
        for(Map.Entry<String, Object> entry:params.entrySet()){
            body.add(entry.getKey(),entry.getValue().toString());
        }
        return body.build();
    }

}

代码分析:该类 OkHttpProcessor 实现了房产公司这个接口,并在对应房产公司服务(post,get)里面实现了 对应网络请求的服务,让房产公司拥有处理 OkHttpProcessor 对应post,get 的能力。

第三步,我们再次创建一个业主,并入驻房产公司(XUtils举例)

public class XUtilsProcessor implements IHttpProcessor {

    public XUtilsProcessor(MyApplication app){
        x.Ext.init(app);
    }

    @Override
    public void post(String url, Map<String, Object> params,final ICallback callback) {
        RequestParams requestParams=new RequestParams(url);
        x.http().post(requestParams, new Callback.CommonCallback<String>() {
            @Override
            public void onSuccess(String result) {
                callback.onSuccess(result);
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {

            }

            @Override
            public void onCancelled(CancelledException cex) {

            }

            @Override
            public void onFinished() {

            }
        });
    }

    @Override
    public void get(String url, Map<String, Object> params, ICallback callback) {

    }
}

到这,房产公司有了,业主也有了多个,并且也入驻了房产公司。那么现在该业务员(中介)出场了

第四步,中介出场 HttpHelper

public class HttpHelper implements IHttpProcessor {

    //定义一个业主,卖房的人
    private static IHttpProcessor mIHttpProcessor=null;

    //通过一个API来设置哪一个业主卖出自己的房子,(谁来完成网络访问)
    public static void init(IHttpProcessor httpProcessor){
        mIHttpProcessor=httpProcessor;
    }

    //单例
    private static HttpHelper instance;
    public static HttpHelper obtain(){
        synchronized (HttpHelper.class){
            if(instance==null){
                instance=new HttpHelper();
            }
        }
        return instance;
    }
    private HttpHelper(){}




    /**
     * 能不能自己卖出房
     */
    @Override
    public void post(String url, Map<String, Object> params, ICallback callback) {
        //http://www.aaa.bbb/index?&user=jett&pwd=123
        //http://www.aaa.bbb/index
        //&user=jett&pwd=123
        String finalUrl=appendParams(url,params);
        mIHttpProcessor.post(url,params,callback);
    }

    @Override
    public void get(String url, Map<String, Object> params, ICallback callback) {

    }

    public static String appendParams(String url, Map<String,Object> params) {
        if(params==null || params.isEmpty()){
            return url;
        }
        StringBuilder urlBuilder=new StringBuilder(url);
        if(urlBuilder.indexOf("?")<=0){
            urlBuilder.append("?");
        }else{
            if(!urlBuilder.toString().endsWith("?")){
                urlBuilder.append("&");
            }
        }
        for(Map.Entry<String,Object> entry:params.entrySet()){
            urlBuilder.append("&"+entry.getKey())
                    .append("=")
                    .append(encode(entry.getValue().toString()));
        }
        return urlBuilder.toString();
    }
    private static String encode(String str){
        try {
            return URLEncoder.encode(str,"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

}

代码分析:该类 HttpHelper 就是我们所说的卖房中介,在这里面先实现房产公司卖房的能力,也对客户(APP)提供了到底要卖哪一套房子(哪个网络框架)的 init 方法 。静态变量 mIHttpProcessor 就是即将要卖房的业主,也就是我们即将要用的网络框架。

到这,所有的准备工作都做好了,现在可以开始交易了

第五步,开始交易

  • MyApplication
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
//        HttpHelper.init(new VolleyProcessor(this));
//        HttpHelper.init(new XUtilsProcessor(this)); 确定使用那一套网络框架
        HttpHelper.init(new OkHttpProcessor());
    }
}
  • MainActivity
public class MainActivity extends AppCompatActivity {

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

    public void click(View view) {
        String url="https://v.juhe.cn/historyWeather/citys";
        HashMap<String,Object> params=new HashMap<>();
        //https://v.juhe.cn/historyWeather/citys?&province_id=2&key=bb52107206585ab074f5e59a8c73875b
        params.put("province_id","2");
        params.put("key","bb52107206585ab074f5e59a8c73875b");
        HttpHelper.obtain().post(url, params, new HttpCallback<ResponceData>() {
            @Override
            public void onSuccess(ResponceData objResult) {
                Toast.makeText(MainActivity.this, objResult.getResultcode(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(String e) {
                super.onFailure(e);
            }
        });

    }
}

代码分析:想必这俩类,不用过多解释了吧,HttpCallback 这个就是刚刚我们所创建的 CallBack扩展类,那个ResponceData 就是网络请求成功 对应json实体对象

下一篇,将讲解 如何使用Hilt快速切换主流框架

Demo地址:点我下载