您的位置:首页 > 理论基础 > 计算机网络

Android 架构师如何选择网络框架

2017-04-23 15:29 393 查看
简介:我们发现目前android网络开发框架越来越多,其实任何一个网络框架都能满足我们的应用开发需求,但是到底哪一个更好,接下来我们从源码角度来分析,到底哪一个更适合我们。
比较:首先我们通过以下几个方面的比较来分析一下(connect实现,线程池管理,可扩展性等)第一方面:首先是connect的实现
volleyokhttpRetrofitAsyncHttpXUtils
HttpURLConnectionImplHttpsURLConnectionImplHttpURLConnectionImplHttpsURLConnectionImplHttpURLConnectionImplHttpsURLConnectionImplDefaultHttpClient(httpclient)HttpURLConnectionImplHttpsURLConnectionImpl
可以看到除了AsyncHttp以外,其他几种框架的connect实现都是相同的,而且可以确切的说用的都是okhttp的实现,到这里也许有人会提出疑问,命名各个框架都是有自己的connect,为什么都用的是volley的呢?下面从源码角度来分析一下。以volley为例分析,其他都是相同的,
/**
* Create an {@link HttpURLConnection} for the specified {@code url}.
*/
protected HttpURLConnection createConnection(URL url) throws IOException {
return (HttpURLConnection) url.openConnection();
}
可以看到都是通过URL的openConnection打开的连接,到URL.java中看一下:
public URLConnection openConnection(Proxy proxy) throws IOException {
if (proxy == null) {
throw new IllegalArgumentException("proxy == null");
}
return streamHandler.openConnection(this, proxy);
}
下面只要知道streamHandler是谁可以了,
void setupStreamHandler() {
.... //忽略掉无用代码

// Fall back to a built-in stream handler if the user didn't supply one
if (protocol.equals("file")) {
streamHandler = new FileHandler();
} else if (protocol.equals("ftp")) {
streamHandler = new FtpHandler();
} else if (protocol.equals("http")) {
try {
String name = "com.android.okhttp.HttpHandler";     //可以看到这里就会实例化okhttp内部的类,接下来就是按照okhttp内部的实现
streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
} else if (protocol.equals("https")) {
try {
String name = "com.android.okhttp.HttpsHandler";
streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
} else if (protocol.equals("jar")) {
streamHandler = new JarHandler();
}
if (streamHandler != null) {
streamHandlers.put(protocol, streamHandler);
}
}
从上面可以看出来,无论任何框架,只要调用了Url.connect(),在系统源码中自动会使用okhttp的connection去处理这里面需要特殊提出来Retrofix,他与其他的有所不同,是完全使用okhttp实现的,
/**
* The factory used to create {@linkplain okhttp3.Call OkHttp calls} for sending a HTTP requests.
* Typically an instance of {@link OkHttpClient}.
*/
public okhttp3.Call.Factory callFactory() {
return callFactory;
}
下面说一下特殊的AnysnHttp,一款老大哥级的网络框架,也是我使用的第一个网络框架,他的底层实现以来httpclient,这个不知道具体什么原因,已经被android废弃了,所以我也不再过多介绍了,简单的列一下代码AsyncHttpRequest.java
private void makeRequest() throws IOException {
if (isCancelled()) {
return;
}

// Fixes #115
if (request.getURI().getScheme() == null) {
// subclass of IOException so processed in the caller
throw new MalformedURLException("No valid URI scheme was provided");
}

if (responseHandler instanceof RangeFileAsyncHttpResponseHandler) {
((RangeFileAsyncHttpResponseHandler) responseHandler).updateRequestHeaders(request);
}

HttpResponse response = client.execute(request, context);

if (isCancelled()) {
return;
}

// Carry out pre-processing for this response.
responseHandler.onPreProcessResponse(responseHandler, response);

if (isCancelled()) {
return;
}

// The response is ready, handle it.
responseHandler.sendResponseMessage(response);

if (isCancelled()) {
return;
}

// Carry out post-processing for this response.
responseHandler.onPostProcessResponse(responseHandler, response);
}
通过上面的比较,真正连接工作的地方实际上是相同的,所以性能相差是不大的,但是由于其他调用的是okhttp的类,而且是反射等方式,所以okhttp理论上应该是优势最大的,但经过笔者测试,几乎没有差别。第二方面 :下面比较各个内部连接池的实现。首先OkHttp/external/okhttp/okhttp/src/main/java/com/squareup/okhttp/Dispatcher.java
public synchronized ExecutorService getExecutorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
可以看到是一个无限大的core_size=0的线程池来管理所有的网络请求再看volley
RequestQueue.java
mDispatchers = new NetworkDispatcher[threadPoolSize];public class NetworkDispatcher extends Thread可以看到volley简单粗暴的就是new出来几个线程,
再来看xutils
HttpTask.java
private static final PriorityExecutor HTTP_EXECUTOR = new PriorityExecutor(5, true);
public PriorityExecutor(int poolSize, boolean fifo) {
BlockingQueue<Runnable> mPoolWorkQueue =
new PriorityBlockingQueue<Runnable>(MAXIMUM_POOL_SIZE, fifo ? FIFO_CMP : FILO_CMP);
mThreadPoolExecutor = new ThreadPoolExecutor(
poolSize,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE,
TimeUnit.SECONDS,
mPoolWorkQueue,
sThreadFactory);
}
可以看到仍然使用的是线程池,只是core_max是5,就是说会始终维持线程,
再来看AnysnHttp在AsyncHttpClient.java 中
    protected ExecutorService getDefaultThreadPool() {return Executors.newCachedThreadPool();}
可以看到使用的是cache的线程池,来进行管理的。可以理解为与okhttp线程池管理方式相同,最后retrofit,因为retrofit底层完全用的是okhttp,所以他和okhttp使用的线程管理方式也是一样的,不再介绍。最后总结一下上面所说的三种线程池管理方式。其实很难说哪个好哪个不好,但是volley的方式过于暴力,1.网络请求频率比较低,仍然有多个线程占用,这是一种浪费,2.当大量的网络请求到来时,线程也没有办法增加,造成请求阻塞,但是他有个好处就是不会因为大量网络请求到来的时候,引起oom对于使用线程池的okhttp和xutils,各有各自的优势,而且都是允许用户自定义线程池的,所以总体来说各有优势。今天先从整体架构角度来分析一下,稍后会对各个细节做进一步的比较。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: