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

前言

本篇文章主要讲解 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实体对象

Demo地址:点我下载

Android相关视频教程推荐

本文转自 https://juejin.cn/post/6983323372734119972,如有侵权,请联系删除。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容