欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中搭建自己的项目网络框架

程序员文章站 2022-03-16 17:32:27
Android发展至今,先后出现了许多流行的网络框架,比如Xutils、OkHttp、Volley、Retrofit等框架,但是作为开发者,我们也应有自己的搭建网络框架的能里,以自...

Android发展至今,先后出现了许多流行的网络框架,比如Xutils、OkHttp、Volley、Retrofit等框架,但是作为开发者,我们也应有自己的搭建网络框架的能里,以自己的项目“量体裁衣”,另一方面,不是每一个网络框架都是没有缺点的比如

Xutils 网络请求框架的弊端:

1、请求方式、地址、参数都拆开了,应该封装到一个对象里面 2、请求之前应该判断网络 3、每次请求都new了一个RequestCallBack对象 4、请求得到的响应不知道是那次请求发出的 5、json的解析封装是耗时的操作不应该放到主线程 6、gson解析用流比字符串效率高很多 7、httpUtils基于HttpClient , HttpUrlConnection 扩展性很差,如果项目要用OkHttp之类的 NoHttp 8、错误的处理不应该让子类来处理 9、请求的响应应该分为三种:成功、其他的情况、错误

现在我们开始搭建网络框架,下面是我们网络搭建的时序图:

Android中搭建自己的项目网络框架

添加依赖 okhttp、Gson

implementation ‘com.squareup.okhttp3:okhttp:3.10.0’ compile
compile ‘com.google.code.gson:gson:2.8.2’

添加权限:


/**
 * Created by MG_ZXC on 2018/3/22.
 * 封装:请求方式, 请求地址, 请求参数
 */

public abstract class BaseRequest {
    public enum HttpMethod{
        GET,POST;
    }
    public abstract HttpMethod getMethod();
    public abstract String getUrl();
    public abstract Map getParams();
}

BaseResponse类封装响应:

/**
 * Created by MG_ZXC on 2018/3/22.
 * 响应json数据的封装
 */

public abstract class BaseResponse  {
    //响应码
    public int code;

    public T data;

    public boolean success() {
        return code >= 200 && code < 300;
    }
}

声明接口 Callback结果回调:

/**
 * Created by MG_ZXC on 2018/3/22.
 * 请求结果回调
 *  为了回调的时候告知当前的响应是哪次请求发出的,响应的方法把请求的BaseRequest传入
 */

public interface Callback   {
     void onError(BaseRequest request, Exception e);
     void onOther(BaseRequest request, Res response);
     void onSuccess(BaseRequest request, Res response);
}

通过NetUtil发送网络请求:

public class NetUtil {
    private static ConnectivityManager connectivityManager;

    public static void init(Context context) {
        connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    private static boolean checkNet() {
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isAvailable();
    }

    /**
     * 通过NetUtil发送网络请求
     *
     * @param request       请求的参数
     * @param responseClass 相应的自字节码
     * @param callback      请求的回调结果
     * @param 
     */
    public static  void sendRequest(BaseRequest request, Class responseClass, Callback callback) {

        //请求之前检查网络
        if (checkNet()) {

            new NetTask().execute(new NetBean(request, responseClass, callback));
        } else {

            callback.onError(request, new IllegalStateException("请检查网络"));
        }
    }

    //需要的对象:BaseRequest, Callback
    private static class NetTask extends AsyncTask {
        @Override
        protected NetBean doInBackground(NetBean[] params) {
            NetBean netBean = params[0];
            try {
                Reader readerResponse = HttpWrapper.getInstance().getReaderResponse(netBean.request);
                BaseResponse response = new Gson().fromJson(readerResponse, netBean.responseClass);
                netBean.response = response;
            } catch (IOException e) {
                e.printStackTrace();
                netBean.exception = e;
            } catch (JsonParseException e) {
                e.printStackTrace();
                netBean.exception = e;
            } catch (Exception e) {
                e.printStackTrace();
                netBean.exception = e;
            }
            return netBean;
        }

        @Override
        protected void onPostExecute(NetBean netBean) {
            //出现了异常
            if (netBean.exception != null) {
                netBean.callback.onError(netBean.request, netBean.exception);
            } else {
                if (netBean.response.success()) {
                    netBean.callback.onSuccess(netBean.request, netBean.response);
                } else {
                    netBean.callback.onOther(netBean.request, netBean.response);
                }
            }
        }
    }

    private static class NetBean {
        public NetBean(BaseRequest request, Class responseClass, Callback callback) {
            this.request = request;
            this.callback = callback;
            this.responseClass = responseClass;
        }

        BaseRequest request;
        Callback callback;
        Class responseClass;
        //json解析封装的结果对象BaseResponse response
        BaseResponse response;
        Exception exception;
    }
}

声明 HttpWrapper 对Http封装 :

/**
 * Created by MG_ZXC on 2018/3/22.
 * Http的封装,真正执行网络请求: OkHttp封装
 */

public class HttpWrapper {
    private volatile static HttpWrapper singleton;
    private final OkHttpClient okHttpClient;

    private HttpWrapper() {
        okHttpClient = new OkHttpClient();
    }

    public static HttpWrapper getInstance() {
        if (singleton == null) {
            synchronized (HttpWrapper.class) {
                if (singleton == null) {
                    singleton = new HttpWrapper();
                }
            }
        }
        return singleton;
    }

    //执行请求 get请求 :请求参数urlusername=zxc&password=123
    //post    在请求体
    public Reader getReaderResponse(BaseRequest request) throws IOException {
        return getResponseBody(request).charStream();
    }

    public String getStringResponse(BaseRequest request) throws IOException {
        return getResponseBody(request).string();
    }

    public byte[] getBytesResponse(BaseRequest request) throws IOException {
        return getResponseBody(request).bytes();
    }

    public InputStream getInputStreamResponse(BaseRequest request) throws IOException {
        return getResponseBody(request).byteStream();
    }

    private ResponseBody getResponseBody(BaseRequest request) throws IOException {
        Request.Builder builder = new Request.Builder();
        if (request.getMethod() == BaseRequest.HttpMethod.GET) {
            StringBuilder stringBuilder = new StringBuilder(request.getUrl());
            Map params = request.getParams();
            if (params != null && params.size() > 0) {
                stringBuilder.append("");
                Set keySet = params.keySet();
                for (String key : keySet) {
                    stringBuilder.append(key).append("=").append(URLEncoder.encode(params.get(key), "UTF-8")).append("&");
                }
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            builder.url(stringBuilder.toString()).get();
        } else if (request.getMethod() == BaseRequest.HttpMethod.POST) {
            //添加请求参数到请求体
            FormBody.Builder formBody = new FormBody.Builder();
            Map params = request.getParams();
            if (params != null && params.size() > 0) {
                Set keySet = params.keySet();
                for (String key : keySet) {
                    formBody.addEncoded(key, params.get(key));
                }
            }
            builder.url(request.getUrl()).post(formBody.build());
        }
        ResponseBody body = okHttpClient.newCall(builder.build()).execute().body();
        return body;
    }
}

使用方式:

1,在 Application 中初始化 :

NetUtil.init(getApplicationContext());

2,使用

NetUtil.sendRequest(new TestRequest(), TestResponse.class, new Callback() {
            @Override
            public void onError(BaseRequest request, Exception e) {

                Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onOther(BaseRequest request, TestResponse response) {

                Toast.makeText(mContext, "其他错误", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onSuccess(BaseRequest request, TestResponse response) {

                TestData data = response.data;
                content.setText(data.toString());
                showSuccesStateView();
            }

        });
public class TestData {
    /**
     * name : sz
     * score : 100
     * sex : true
     */

    private String name;
    private int score;
    private boolean sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "TestData{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", sex=" + sex +
                '}';
    }
}
public class TestResponse extends BaseResponse {
}
public class TestRequest implements BaseRequest {
    @Override
    public HttpMethod getMethod() {
        return HttpMethod.POST;
    }

    @Override
    public String getUrl() {
        return Constant.format("TestServlet");
    }

    @Override
    public Map getParams() {
        HashMap map = new HashMap<>();
        map.put("username", "itcast");
        map.put("password", "123&heima");
        return map;
    }
}

以上是网络框架的基本用法。实际上在开发中还可以优化形式出现比如(在基类中进行除数据请求成功的页面设置,在子类中进行,发送数据请求和处理数据请求正确的情况的):

在基类BaseFragment:

  private OnSuccessCallback mOnSuccessCallback;
    //由父类发出请求在通知子类,错误,空数据由父类处理
    public void sendRequest(BaseRequest request, Class responseClass, OnSuccessCallback onSuccessCallback) {

        mOnSuccessCallback = onSuccessCallback;
        NetUtil.sendRequest(request, responseClass, this);
    }

    @Override
    public void onError(BaseRequest request, Exception e) {
         //在基类中统一进行错误处理,比如错误页面的展示
    }

    @Override
    public void onOther(BaseRequest request, BaseResponse response) {
        Toast.makeText(mContext, "其他错误", Toast.LENGTH_SHORT).show();
    }

    //请求通知子类 
    @Override
    public void onSuccess(BaseRequest request, BaseResponse response) {

        if (response == null || response.data == null) {
            // 数据为空的情况
        } else {
            //展示成功页面由子类处理
            mOnSuccessCallback.onSuccess(request, response);
        }
    }

声明数据请求成功的情况的接口

public interface OnSuccessCallback {
    public void onSuccess(BaseRequest request, Res response);
}

在子类中进行处理成功数据请求情况:

//调用父类sendRequest
sendRequest(new TestRequest(), TestResponse.class, new OnSuccessCallback() {
  @Override
  public void onSuccess(BaseRequest request, TestResponse response) {
      //获取请求数据
 }