XUtils源码分析之HttpUtils(一)

本文详细介绍了如何使用HttpUtils构造HTTP客户端请求,包括不同构造函数的使用、并行发送请求的方法及内部实现原理,并探讨了同步请求的具体流程和重试机制。

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

一、new HttpClient()构造函数

1、三种构造显示的构造方式:

public HttpUtils(int connTimeout, String userAgent)定义请求的connectionTimeout和客户端使用的代理设置。
HttpUtils(String userAgent)
HttpUtils(int connTimeout)

2、使用apache的DefaultHttpClient进行实现,在构造函数中进行预设值。

1、使用connTimeout进行超时的设定
2、代理的设定,如果是null的话,先使用android默认使用的代理,通过反射进行得到:

sysResCls = Class.forName("com.android.internal.R$string");
Field webUserAgentField = sysResCls.getDeclaredField("web_user_agent");
Integer resId = (Integer) webUserAgentField.get(null);
webUserAgent = this.getString(resId);

以上得到(2015-06-08打印)
Mozilla/5.0 (Linux; U; Android %s) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 %sSafari/534.30

否则,使用自己设置的默认的代理服务器(这个最好还是要和上面的保持最新):
Mozilla/5.0 (Linux; U; Android %s) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 %sSafari/533.1

3、进行了HttpUtils的构造之后,用户能够进行自定义的某些功能的配置。

http_0

二、send(并行方式进行request请求)

1、HttpRequest请求的构造

>

1.1、HttpRequest extends HttpRequestBase implements HttpEntityEnclosingRequest使用apache的HttpRequestBase类,该类提供了构造HttpRequest的基本属性和方法,并实现了HttpEntityEnclosingRequest这个接口,该接口中定义了getEntitysetEntity方法,方便entity的获取。
1.2、在HttpRequest构造参数中,传入“method”和“uri”,这样,就可以构造一个httprequest了。
1.3、

HttpHandler handler = new HttpHandler(httpClient, httpContext, responseTextCharset, callBack); 
handler.setExpiry(currentRequestExpiry);
handler.setHttpRedirectHandler(httpRedirectHandler);
request.setRequestParams(params, handler);
if (params != null) {
handler.setPriority(params.getPriority());
}
handler.executeOnExecutor(EXECUTOR, request);
return handler;

设置一个Handler处理器,将这个request进行处理。

2、具体executeOnExecutor请求的处理

1、使用线程处理器Executor去执行这个task:
public final PriorityAsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
if (mExecuteInvoked) {
throw new IllegalStateException("Cannot execute task:"
+ " the task is already executed.");
}
mExecuteInvoked = true;
onPreExecute();
mWorker.mParams = params;
exec.execute(new PriorityRunnable(priority, mFuture));
return this;
}

mExecutorInvoked表示是否这个task正在执行,现进行判断,执行的时候,将这个值置为true;
2、使用Callable和FutureTask的方式并行的运行线程,使用Executor进行线程的执行。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public PriorityAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
LogUtils.d(e.getMessage());
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}

先定义一个WorkerRunnable,传入希望运行的参数;继而定义一个Futuretask,获取到get()执行的结果,并在

private Result postResult(Result result) { 
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
中将最后结果的值使用Handler传递给MainThread。

3、以上就是send(并行)方法执行的过程。

##三、sendSync(同步)执行请求。 ###1、同步请求比较简单,大概步骤就是: ####1.1、cache将运行的结果存储在LRUCache中;下次执行一个对资源URI的请求的时候,先从cache中找到结果,如果能找到,就直接返回,否则执行网络请求。 ####1.2、进行retryHandler的对象的建立,执行网络请求的时候,如果出现了一些希望重连的情况,要不断的进行重连。所以,这部分网络的请求,要使用while(true)的循环不断重连。 ####1.3、在遇到我们不希望重连的情况的时候,直接抛出异常,中断执行,跳出while循环。
1.4、代码如下:
public ResponseStream sendRequest(HttpRequestBase request) throws HttpException {
        HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();
        while (true) {
            boolean retry = true;
            IOException exception = null;
            try {
                requestUrl = request.getURI().toString();
                requestMethod = request.getMethod();
                if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {
                    String result = HttpUtils.sHttpCache.get(requestUrl);
                    if (result != null) {
                        return new ResponseStream(result);
                    }
                }
                HttpResponse response = client.execute(request, context);
                return handleResponse(response);
            } catch (UnknownHostException e) {
                exception = e;
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (IOException e) {
                exception = e;
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (NullPointerException e) {
                exception = new IOException(e.getMessage());
                exception.initCause(e);
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (HttpException e) {
                throw e;
            } catch (Throwable e) {
                exception = new IOException(e.getMessage());
                exception.initCause(e);
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            }
            if (!retry) {
                throw new HttpException(exception);
            }
        }
    }

可知:希望retry的情况是boolean retryRequest(IOException var1, int var2, HttpContext var3);这里catch住的异常应该是IOException的子类,并且,如果是我们希望retry的异常,我们要人工的将catch的异常转化成IOException异常。
最终抛出HttpException。

1.5、需要注意的是:只有GET请求这类幂等性的请求,才能进行retry重连。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值