一步步打造网络请求框架——功能扩展(三)

本文档详细介绍了如何在已有的网络请求框架基础上添加网络请求取消功能,通过在`RequestTask`中设置一个原子布尔变量,并在`onDestroy()`中取消任务。同时,展示了`RequestManager`和`CommonRequest`类的修改,以便在Activity销毁时能够正确取消网络请求。此外,代码还展示了如何随着业务需求扩展网络框架,以提高其适应性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章重点介绍了如何优化现有的网络框架,本篇文章重点分析,在此基础上一步步打造网络请求框架——细节优化(二),如何进行功能上的扩展,让框架的适应性更强。

上一篇文章末尾提到,网络请求取消的功能还没有,那么,今天就把这个功能分析一下并且做出来,再看看还有没有别的方面的扩展。

关于网络请求取消,大多数情况下是我们的Acticity关闭了以后,而后台网络请求还在执行,此时最好将当前的网络请求取消(因为页面已经关闭,请求实际上没有意义了),那具体操作就是在onDestory()中操作当前线程池正在处理的任务,并且将他取消。

在RequestTask中加入部分代码:

public class RequestTask implements Runnable {
    private static final String             TAG        = RequestTask.class.getSimpleName();
    private              String             url;
    private              Map<String,String> params;
    private              Map<String,String> headers;
    private              HttpMethod         httpMethod;
    private              JsonCallback       mJsonCallback;
    private              Context            mContext;
    private static       InternalHandler    sHandler;
    private final        AtomicBoolean   mCancelled = new AtomicBoolean();
    private              boolean         isCompleted;
    public RequestTask(CommonRequest request) {
        this.url = request.getUrl();
        this.params = request.getParams();
        this.headers = request.getHeaders();
        this.httpMethod = request.getHttpMethod();
        this.mJsonCallback = request.getJsonCallback();
        this.mContext = request.getContext();
    }

    public boolean isCompleted() {
        return isCompleted;
    }

    public void execute() {
        CoreExecutorService.getExecutorService().submit(this);
    }

    public final void cancel() {
        mCancelled.set(true);
        CoreExecutorService.cancel(this);
    }

    public boolean isCancelled() {
        return mCancelled.get();
    }
    @Override
    public void run() {
        if (isCancelled()) {
            onFailure(new HttpException(HttpException.ErrorType.CANCEL, "the request has been cancelled"));
            LogUtils.e(TAG, "the request has been cancelled");
            return;
        }
        if (!NetWorkUtil.isConnect(mContext)) {
            //断网处理
            onFailure(new HttpException(HttpException.ErrorType.IO, "请检查网络连接是否正常"));
            return;
        }
        Response response;
        String json;
        if (httpMethod == HttpMethod.GET) {
            if (headers != null && headers.size() > 0) {
                response = HttpUtil.get(url, headers);
            } else {
                response = HttpUtil.get(url);
            }
        } else if (httpMethod == HttpMethod.POST) {
            response = HttpUtil.post(url, params, headers);
        } else if (httpMethod == HttpMethod.PUT) {
            response = HttpUtil.put(url, params);
        } else {
            response = HttpUtil.delete(url, params);
        }
        try {
            if (response != null) {
                if (response.body() != null) {
                    json = response.body().string();
                    if (!TextUtils.isEmpty(json)) {
                        LogUtils.i(TAG, json);
                        JSONObject jsonObject = new JSONObject(json);
                        if (jsonObject.has("code")) {
                            int code = jsonObject.optInt("code");
                            String message = jsonObject.optString("msg");
                            String type = jsonObject.optString("type");
                            String data = jsonObject.optString("data");
                            LogUtils.i(TAG, "需要解析的数据 :" + data);
                            if (code == 1) {
                                Object o = mJsonCallback.bindData(data);
                                onSuccess(o);
                                isCompleted = true;
                            } else {
                                onFailure(new HttpException(code, message));
                            }
                        } else {
                            onFailure(new HttpException(HttpException.ErrorType.JSON, "json error"));
                        }
                    } else {
                        //Json为空
                        onFailure(new HttpException(HttpException.ErrorType.SERVER, "json empty"));
                        return;
                    }
                }
            }
        } catch(Exception e){
            LogUtils.e(TAG, "error---" + e.toString());
            e.printStackTrace();
            onFailure(e);
        }

    }



    private void onFailure(final Exception e) {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                mJsonCallback.onFailure(e);
            }
        });
    }

    private void onSuccess(final Object o) {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                mJsonCallback.onSuccess(o);
            }
        });
    }

    private static class InternalHandler extends Handler {
        InternalHandler() {
            super(Looper.getMainLooper());
        }
    }

    private static InternalHandler getHandler() {
        if (sHandler == null) {
            synchronized (RequestTask.class) {
                if (sHandler == null) {
                    sHandler = new InternalHandler();
                }
            }
        }
        return sHandler;
    }
}

其中,cancel()方法调用到线程池中的cancel()中,将线程池中的任务删除

public static void cancel(Runnable task){
        sPoolWorkQueue.remove(task);
    }

接下来修改RequestManager和CommonRequest类

public class RequestManager {
    private static RequestManager                           sRequestManager;
    private        ArrayMap<String, ArrayList<RequestTask>> mExecutedTask;
    private RequestManager(){
        mExecutedTask = new ArrayMap<>();
    }
    public static RequestManager getRequestManager(){
        if(sRequestManager == null){
            synchronized (RequestManager.class){
                if(sRequestManager == null){
                    sRequestManager = new RequestManager();
                }
            }
        }
        return sRequestManager;
    }
    public void performRequest(CommonRequest request){
        RequestTask task = new RequestTask(request);
        task.execute();

        if(!mExecutedTask.containsKey(request.getTag())){
            ArrayList<RequestTask> tasks = new ArrayList<>();
            tasks.add(task);
            mExecutedTask.put(request.getTag(),tasks);
        }else {
            ArrayList<RequestTask> tasks = mExecutedTask.get(request.getTag());
            if(tasks != null && tasks.size() > 0){
                tasks.add(task);
            }
        }
    }
    public void cancelRequest(String tag){
        if(tag == null || tag.equals("")){
            return;
        }
        if(mExecutedTask.containsKey(tag)){
            ArrayList<RequestTask> tasks = mExecutedTask.get(tag);
            if(tasks != null && tasks.size() > 0){
                for (RequestTask task: tasks) {
                    if(task != null){
                        if(!task.isCancelled() && !task.isCompleted()){
                            task.cancel();
                        }
                    }
                }
            }
        }
    }
}
public class CommonRequest {
    private String mUrl;
    private Map<String,String> mParams;
    private Map<String,String> mHeaders;
    private HttpMethod mHttpMethod;
    private JsonCallback mJsonCallback;
    private Context mContext;
    private String              mTag;

    public CommonRequest(Builder builder) {
        this.mUrl = builder.mUrl;
        this.mParams = builder.mParams;
        this.mHeaders = builder.mHeaders;
        this.mHttpMethod = builder.mHttpMethod;
        this.mJsonCallback = builder.mJsonCallback;
        this.mContext = builder.mContext;
        this.mTag = builder.mTag;
    }

    public String getTag() {
        return mTag;
    }

    public Context getContext() {
        return mContext;
    }

    public String getUrl() {
        return mUrl;
    }

    public Map<String, String> getParams() {
        return mParams;
    }

    public Map<String, String> getHeaders() {
        return mHeaders;
    }

    public HttpMethod getHttpMethod() {
        return mHttpMethod;
    }

    public JsonCallback getJsonCallback() {
        return mJsonCallback;
    }

    public static class Builder{
        private String mUrl;
        private Map<String,String> mParams;
        private Map<String,String> mHeaders;
        private HttpMethod mHttpMethod;
        private JsonCallback mJsonCallback;
        private Context mContext;
        private String              mTag;

        public Builder setTag(String tag) {
            mTag = tag;
            return this;
        }

        public Builder setContext(Context context) {
            mContext = context;
            return this;
        }

        public Builder setUrl(String url) {
            mUrl = url;
            return this;
        }

        public Builder setParams(Map<String, String> params) {
            mParams = params;
            return this;
        }

        public Builder setHeaders(Map<String, String> headers) {
            mHeaders = headers;
            return this;
        }

        public Builder setHttpMethod(HttpMethod httpMethod) {
            mHttpMethod = httpMethod;
            return this;
        }

        public Builder setJsonCallback(JsonCallback jsonCallback) {
            mJsonCallback = jsonCallback;
            return this;
        }
        public CommonRequest build(){
            return new CommonRequest(this);
        }
    }
}

并且在Activity中的onDestory()中调用取消网络请求的方法

 @Override
    protected void onDestroy() {
        super.onDestroy();
        RequestManager.getRequestManager().cancelRequest(TAG);
    }

上面的代码当中:TAG就是表示当前Activity的一个字符串,一般用MainActivity.class.getSimpleName()表示。在RequestManager中,我们使用了一个ArrayMap来存储当前的Activity标识和任务集合,即一个Tag对应一个List,如果当前Activity是一个列表页面,那就会有很多个网络请求,把这些网络任务全部保存在一个List当中,并且绑定对应的Activity,在Activity被销毁时,这些网络任务也就会被一一遍历出来取消掉,而具体取消任务的工作交给线程池去完成。

OK,这样一来取消网络请求的功能也已经完成,随着业务的不断增多,我们的框架也会随着业务不断完善,还有更多的功能等待我们去扩展。这三篇文章所介绍的网络框架我也用了好多年了,在此期间,也随着业务的更新去不断重构这个框架,功能还包括:支持多文件上传,支持文件下载 ,支持本地缓存(有的类似于新闻阅读类App可能有这样的需求:先加载之前缓存的本地数据,再从网络请求数据并更新UI),全部代码都已经上传了本人的Github——Http框架,上面有全部的介绍。

在机器人操作系统(ROS)中,机器视觉是机器人感知和理解周围环境的关键技术。robot_vision功能包专注于这一领域,集成了多种视觉处理技术,包括摄像头标定、OpenCV库应用、人脸识别、物体跟踪、二维码识别和物体识别,极大地拓展了ROS在视觉应用方面的能力。 摄像头标定:作为机器视觉的基础,摄像头标定用于消除镜头畸变并获取相机的内参和外参。在ROS中,camera_calibration包提供了友好的用户界面和算法,帮助计算相机参数矩阵,为后续的图像校正和维重建提供支持。 OpenCV:OpenCV是一个广泛使用的开源计算机视觉库,在ROS中扮演着重要角色。robot_vision功能包可能包含OpenCV的示例代码和节点,涵盖图像处理、特征检测、模板匹配和图像分割等功能,这些功能对机器人视觉系统至关重要。 人脸识别:ROS中的人脸识别结合了图像处理和机器学习技术。robot_vision可能集成了基于OpenCV的人脸检测算法,如Haar级联分类器或Adaboost方法,甚至可能包含深度学习模型(如FaceNet或SSD),帮助机器人实现人脸的识别和跟踪,提升人机交互能力。 物体跟踪:物体跟踪使机器人能够持续关注并追踪特定目标。在ROS中,通常通过卡尔曼滤波器、粒子滤波器或光流法实现。robot_vision功能包可能包含这些算法的实现,助力机器人完成动态目标跟踪任务。 二维码识别:二维码是一种高效的信息编码方式,常用于机器人定位和导航。ROS中的二维码包可用于读取和解析二维码,而robot_vision可能进一步封装了这一功能,使其更易于集成到机器人系统中。 物体识别:作为机器视觉的高级应用,物体识别通常涉及深度学习模型,如YOLO、SSD或Faster R-CNN。robot_vision功能包可能包含预训练的模型和对应的ROS节点,使机器人能够识别环境中的特
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值