精华内容
下载资源
问答
  • 主要为大家详细介绍了Android最基本的异步网络请求框架,感兴趣的小伙伴们可以参考一下
  • 现在各种网络请求框架五花八门,不过大多都是粘贴来粘贴去的,着实让人蛋疼。 现在整理出一个条理清晰,使用起来很方便的框架,是基于android_asynchttp_client
  • IOS开发中异步网络请求上实现同步逻辑 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不需要上传了,直接报错。 之前ASI的网络库...
  • Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnection,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用这个MyHttpUtils库可以大大的简化操作,它是基于...
  • 判断网络请求进行中数量是否大于最大请求和 ip(域名)相同不超过maxRequestsPerHost  if (runningAsyncCalls.size() (call) ) { runningAsyncCalls.add(call);//符合 添加到异步运行容器中  executorService()....

     直接上码:

    	public void doGet(View view) {
    
    		Request request = new Request.Builder().url(BASEURL + "login")
    				.get().cacheControl(CacheControl.FORCE_NETWORK).build();
    		okHttpClient.newCall(request).enqueue(new Callback() {
    			@Override
    			public void onFailure(Call call, IOException e) {
    				Log.e(TAG, "onFailure: " + call.toString());
    			}
    
    			@Override
    			public void onResponse(Call call, Response response) throws IOException {
    				Log.e(TAG, "onResponse: " + response.body().string());
    			}
    		});
    	}public void doGet(View view) {
    
    		Request request = new Request.Builder().url(BASEURL + "login")
    				.get().cacheControl(CacheControl.FORCE_NETWORK).build();
    		okHttpClient.newCall(request).enqueue(new Callback() {
    			@Override
    			public void onFailure(Call call, IOException e) {
    				Log.e(TAG, "onFailure: " + call.toString());
    			}
    
    			@Override
    			public void onResponse(Call call, Response response) throws IOException {
    				Log.e(TAG, "onResponse: " + response.body().string());
    			}
    		});
    	}

    跟使用同步方法是相差一个enqueque()方法:

      @Override public void enqueue(Callback responseCallback) {
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already Executed");
          executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        client.dispatcher().enqueue(new AsyncCall(responseCallback)); 创建一个ASyncCall 对象交给 dispather
      }

     dispathcher.enqueque(...) :

    synchronized void enqueue(AsyncCall call) {
    判断网络请求进行中数量是否大于最大请求和 ip(域名)相同不超过maxRequestsPerHost 
     if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
    runningAsyncCalls.add(call);//符合 添加到异步运行容器中
     executorService().execute(call);// 然后线程池调度器去执行 call 
    }
    else 
    { 
    readyAsyncCalls.add(call); //不符合添加到等待队列中
     }
     }
    因为是使用executorService.execute(..) 参数是call  所以AsyncCall必然是继承Runable子类或者实现了Runable.

    AsyncCall 继承的是 NamedRunable(Runable的子类) 并实现了抽象execute()方法

     @Override protected void execute() {
          boolean signalledCallback = false;
          try {
            Response response = getResponseWithInterceptorChain(); 去执行网络请求
            if (retryAndFollowUpInterceptor.isCanceled()) { 是否取消
              signalledCallback = true;
              responseCallback.onFailure(RealCall.this, new IOException("Canceled"));错误(取消)回调
            } else {
              signalledCallback = true;
              responseCallback.onResponse(RealCall.this, response);成功回调
            }
          } catch (IOException e) {
            if (signalledCallback) {
              // Do not signal the callback twice!
              Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
            } else {
              eventListener.callFailed(RealCall.this, e);
              responseCallback.onFailure(RealCall.this, e);
            }
          } finally {
            client.dispatcher().finished(this); 这里是从异步容器中移除并判断是否有read..容器中网络请求有
    添加到线程调度器中执行,没有或者大于最大请求 good bye
     }
        }
      }


    Dispather: 存放AsyncCall和并使 AsyncCall 的中网络请求方法在子线程执行
    流程图如下:

     

    展开全文
  • Python2 异步网络请求库比较

    千次阅读 2018-08-26 01:52:28
    requests作者写的基于gevent的异步请求库。 地址 https://github.com/kennethreitz/grequests 示例 import grequests urls = [ 'http://www.heroku.com', 'http://python-tablib.org', ...

    封装库

    grequests

    简介

    requests作者写的基于gevent的异步请求库。

    地址

    https://github.com/kennethreitz/grequests

    示例

    import grequests
    
    urls = [
        'http://www.heroku.com',
        'http://python-tablib.org',
        'http://httpbin.org',
        'http://python-requests.org',
        'http://fakedomain/',
        'http://kennethreitz.com'
    ]
    rs = (grequests.get(u) for u in urls)
    grequests.map(rs)

    get方法参数与requests.get()参数相同,当然也支持postputdelete等方法。
    请求失败默认返回None,可以给map方法传递。exception_handler参数指定请求失败的回调函数。

    map支持的参数如下:

    :param requests: a collection of Request objects.
    :param stream: If True, the content will not be downloaded immediately.
    :param size: Specifies the number of requests to make at a time. If None, no throttling occurs.
    :param exception_handler: Callback function, called when exception occured. Params: Request, Exception
    :param gtimeout: Gevent joinall timeout in seconds. (Note: unrelated to requests timeout)

    另外如果要希望返回生成器可以使用imap方法。不过imap方法size默认为2,且没有gtimeout参数。

    requests-threads

    简介

    requests作者的另一个异步请求模块,基于Twisted框架。

    地址

    https://github.com/requests/requests-threads

    示例

    from twisted.internet.defer import inlineCallbacks
    from twisted.internet.task import react
    from requests_threads import AsyncSession
    
    session = AsyncSession(n=100)
    
    @inlineCallbacks
    def main(reactor):
        responses = []
        for i in range(100):
            responses.append(session.get('http://httpbin.org/get'))
    
        for response in responses:
            r = yield response
            print(r)
    
    if __name__ == '__main__':
        react(main)

    txrequests

    简介

    同样是基于twisted框架的异步requests模块。

    地址

    https://github.com/tardyp/txrequests

    示例

    from txrequests import Session
    from twisted.internet import defer
    
    @defer.inlineCallbacks
    def main():
        # use with statement to cleanup session's threadpool, and connectionpool after use
        # you can also use session.close() if want to use session for long term use
        with Session() as session:
            # first request is started in background
            d1 = session.get('http://httpbin.org/get')
            # second requests is started immediately
            d2 = session.get('http://httpbin.org/get?foo=bar')
            # wait for the first request to complete, if it hasn't already
            response_one = yield d1
            print('response one status: {0}'.format(response_one.status_code))
            print(response_one.content)
            # wait for the second request to complete, if it hasn't already
            response_two = yield d2
            print('response two status: {0}'.format(response_two.status_code))
            print(response_two.content)

    treq

    简介

    基于twisted的异步网络请求库,致力于提供与requests类似的接口。此模块文档较完善。

    地址

    https://github.com/twisted/treq

    示例

    def main(reactor, *args):
        d = treq.get('http://httpbin.org/get')
        d.addCallback(print_response)
        return d

    trip

    简介

    基于tornado的异步网络请求库。

    地址

    https://github.com/littlecodersh/trip

    示例

    import trip
    
    def main():
        r = yield trip.get('https://httpbin.org/get', auth=('user', 'pass'))
        print(r.content)
    
    trip.run(main)

    底层库

    gevent

    简介

    Python2中最常见的异步库。

    地址

    https://github.com/gevent/gevent

    示例

    import gevent
    from gevent import socket
    urls = ['www.google.com', 'www.example.com', 'www.python.org']
    jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls
    gevent.joinall(jobs, timeout=2)
    [job.value for job in jobs]

    自动将网络请求转换为异步模式的monkey patch:

    from gevent import monkey
    monkey.patch_socket()
    import urllib2
    展开全文
  • Android 异步网络请求框架-Volley

    千次阅读 2016-01-11 13:32:46
    Android 异步网络请求框架-Volley1. 功能介绍1.1. VolleyVolley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。 名字由来:a burst or emission of many things or a ...

    Android 异步网络请求框架-Volley

    1. 功能介绍

    1.1. Volley

    Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。
    名字由来:a burst or emission of many things or a large amount at once
    发布演讲时候的配图
    这里写图片描述
    Volley 的特点:特别适合数据量小,通信频繁的网络操作。(Android 应用中绝大多数的网络操作都属于这种类型)。

    1.2 Volley 的主要特点

    (1). 扩展性强。Volley 中大多是基于接口的设计,可配置性强。
    (2). 一定程度符合 Http 规范,包括返回 ResponseCode(2xx、3xx、4xx、5xx)的处理,请求头的处理,缓存机制的支持等。并支持重试及优先级定义。
    (3). 默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现,这两者的区别及优劣在4.2.1 Volley中具体介绍。
    (4). 提供简便的图片加载工具。

    2. 总体设计

    2.1 总体设计图

    这里写图片描述
    上面是 Volley 的总体设计图,主要是通过两种Dispatch Thread不断从RequestQueue中取出请求,根据是否已缓存调用Cache或Network这两类数据获取接口之一,从内存缓存或是服务器取得请求的数据,然后交由ResponseDelivery去做结果分发及回调处理。
    2.2 Volley 中的概念
    简单介绍一些概念,在详细设计中会仔细介绍。
    Volley 的调用比较简单,通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue后,只需要往这个RequestQueue不断 add Request 即可。
    Volley:Volley 对外暴露的 API,通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue。
    Request:表示一个请求的抽象类。StringRequest、JsonRequest、ImageRequest 都是它的子类,表示某种类型的请求。
    RequestQueue:表示请求队列,里面包含一个CacheDispatcher(用于处理走缓存请求的调度线程)、NetworkDispatcher数组(用于处理走网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 函数启动时会启动CacheDispatcher和NetworkDispatchers。
    CacheDispatcher:一个线程,用于调度处理走缓存的请求。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher去调度处理。
    NetworkDispatcher:一个线程,用于调度处理走网络的请求。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理,并判断结果是否要进行缓存。
    ResponseDelivery:返回结果分发接口,目前只有基于ExecutorDelivery的在入参 handler 对应线程内进行分发。
    HttpStack:处理 Http 请求,返回请求结果。目前 Volley 中有基于 HttpURLConnection 的HurlStack和 基于 Apache HttpClient 的HttpClientStack。
    Network:调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
    Cache:缓存请求结果,Volley 默认使用的是基于 sdcard 的DiskBasedCache。NetworkDispatcher得到请求结果后判断是否需要存储在 Cache,CacheDispatcher会从 Cache 中取缓存结果。

    3. 流程图

    Volley 请求流程图:
    这里写图片描述

    4. 详细设计

    4.1 类关系图

    这里写图片描述
    这是 Volley 框架的主要类关系图
    图中红色圈内的部分,组成了 Volley 框架的核心,围绕 RequestQueue 类,将各个功能点以组合的方式结合在了一起。各个功能点也都是以接口或者抽象类的形式提供。
    红色圈外面的部分,在 Volley 源码中放在了 toolbox 包中,作为 Volley 为各个功能点提供的默认的具体实现。
    通过类图我们看出, Volley 有着非常好的拓展性。通过各个功能点的接口,我们可以给出自定义的,更符合我们需求的具体实现。

    4.2 核心类功能介绍

    4.2.1 Volley.java

    这个和 Volley 框架同名的类,其实是个工具类,作用是构建一个可用于添加网络请求的RequestQueue对象。
    (1). 主要函数
    Volley.java 有两个重载的静态方法。
    public static RequestQueue newRequestQueue(Context context)

    public static RequestQueue newRequestQueue(Context context, HttpStack stack)
    第一个方法的实现调用了第二个方法,传 HttpStack 参数为 null。
    第二个方法中,如果 HttpStatck 参数为 null,则如果系统在 Gingerbread 及之后(即 API Level >= 9),采用基于 HttpURLConnection 的 HurlStack,如果小于 9,采用基于 HttpClient 的 HttpClientStack。

    if (stack == null) {
        if (Build.VERSION.SDK_INT >= 9) {
            stack = new HurlStack();
        } else {
            stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
        }
    }

    得到了 HttpStack,然后通过它构造一个代表网络(Network)的具体实现BasicNetwork。
    接着构造一个代表缓存(Cache)的基于 Disk 的具体实现DiskBasedCache。
    最后将网络(Network)对象和缓存(Cache)对象传入构建一个 RequestQueue,启动这个 RequestQueue,并返回。

    Network network = new BasicNetwork(stack);
    RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
    queue.start();
    return queue;

    我们平时大多采用Volly.newRequestQueue(context)的默认实现,构建 RequestQueue。
    通过源码可以看出,我们可以抛开 Volley 工具类构建自定义的 RequestQueue,采用自定义的HttpStatck,采用自定义的Network实现,采用自定义的 Cache 实现等来构建RequestQueue。

    (2). HttpURLConnection 和 AndroidHttpClient(HttpClient 的封装)如何选择及原因:
    在 Froyo(2.2) 之前,HttpURLConnection 有个重大 Bug,调用 close() 函数会影响连接池,导致连接复用失效,所以在 Froyo 之前使用 HttpURLConnection 需要关闭 keepAlive。
    另外在 Gingerbread(2.3) HttpURLConnection 默认开启了 gzip 压缩,提高了 HTTPS 的性能,Ice Cream Sandwich(4.0) HttpURLConnection 支持了请求结果缓存。
    再加上 HttpURLConnection 本身 API 相对简单,所以对 Android 来说,在 2.3 之后建议使用 HttpURLConnection,之前建议使用 AndroidHttpClient。

    4.2.2 Request.java

    代表一个网络请求的抽象类。我们通过构建一个Request类的非抽象子类(StringRequest、JsonRequest、ImageRequest 或自定义)对象,并将其加入到•RequestQueue•中来完成一次网络请求操作。
    Volley 支持 8 种 Http 请求方式 GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, PATCH
    Request 类中包含了请求 url,请求请求方式,请求 Header,请求 Body,请求的优先级等信息。
    因为是抽象类,子类必须重写的两个方法。
    abstract protected Response parseNetworkResponse(NetworkResponse response);
    子类重写此方法,将网络返回的原生字节内容,转换成合适的类型。此方法会在工作线程中被调用。
    abstract protected void deliverResponse(T response);
    子类重写此方法,将解析成合适类型的内容传递给它们的监听回调。
    以下两个方法也经常会被重写

    public byte[] getBody()

    重写此方法,可以构建用于 POST、PUT、PATCH 请求方式的 Body 内容。
    protected Map

    4.2.3 RequestQueue.java

    Volley 框架的核心类,将请求 Request 加入到一个运行的RequestQueue中,来完成请求操作。
    (1). 主要成员变量
    RequestQueue 中维护了两个基于优先级的 Request 队列,缓存请求队列和网络请求队列。
    放在缓存请求队列中的 Request,将通过缓存获取数据;放在网络请求队列中的 Request,将通过网络获取数据。

    private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<?>>();
    private final PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<Request<?>>();

    维护了一个正在进行中,尚未完成的请求集合。

    private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();

    维护了一个等待请求的集合,如果一个请求正在被处理并且可以被缓存,后续的相同 url 的请求,将进入此等待队列。

    private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();

    (2). 启动队列
    创建出 RequestQueue 以后,调用 start 方法,启动队列。

    /**
     * Starts the dispatchers in this queue.
     */
    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();
    
        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }

    start 方法中,开启一个缓存调度线程CacheDispatcher和 n 个网络调度线程NetworkDispatcher,这里 n 默认为 4,存在优化的余地,比如可以根据 CPU 核数以及网络类型计算更合适的并发数。
    缓存调度线程不断的从缓存请求队列中取出 Request 去处理,网络调度线程不断的从网络请求队列中取出 Request 去处理。
    (3). 加入请求

    public <T> Request<T> add(Request<T> request);

    这里写图片描述
    流程图如下:
    这里写图片描述
    (4). 请求完成

    void finish(Request<?> request)

    Request 请求结束:
    这里写图片描述
    (1). 首先从正在进行中请求集合mCurrentRequests中移除该请求。
    (2). 然后查找请求等待集合mWaitingRequests中是否存在等待的请求,如果存在,则将等待队列移除,并将等待队列所有的请求添加到缓存请求队列中,让缓存请求处理线程CacheDispatcher自动处理。
    (5). 请求取消

    public void cancelAll(RequestFilter filter)
    public void cancelAll(final Object tag)

    取消当前请求集合中所有符合条件的请求。
    filter 参数表示可以按照自定义的过滤器过滤需要取消的请求。
    tag 表示按照Request.setTag设置好的 tag 取消请求,比如同属于某个 Activity 的。

    4.2.4 CacheDispatcher.java

    一个线程,用于调度处理走缓存的请求。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery 去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher去调度处理。
    (1). 成员变量

    BlockingQueue<Request<?>> mCacheQueue 缓存请求队列
    BlockingQueue<Request<?>> mNetworkQueue 网络请求队列
    Cache mCache 缓存类,代表了一个可以获取请求结果,存储请求结果的缓存
    ResponseDelivery mDelivery 请求结果传递类

    (2). 处理流程图
    这里写图片描述

    4.2.5 NetworkDispatcher.java

    一个线程,用于调度处理走网络的请求。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给 ResponseDelivery 去执行后续处理,并判断结果是否要进行缓存。
    (1). 成员变量

    BlockingQueue<Request<?>> mQueue 网络请求队列
    Network mNetwork 网络类,代表了一个可以执行请求的网络
    Cache mCache 缓存类,代表了一个可以获取请求结果,存储请求结果的缓存
    ResponseDelivery mDelivery 请求结果传递类,可以传递请求的结果或者错误到调用者

    (2). 处理流程图
    这里写图片描述

    4.2.6 Cache.java

    缓存接口,代表了一个可以获取请求结果,存储请求结果的缓存。
    (1). 主要方法:

    public Entry get(String key); 通过 key 获取请求的缓存实体
    public void put(String key, Entry entry); 存入一个请求的缓存实体
    public void remove(String key); 移除指定的缓存实体
    public void clear(); 清空缓存

    (2). 代表缓存实体的内部类 Entry
    成员变量和方法

    byte[] data 请求返回的数据(Body 实体)
    String etag Http 响应首部中用于缓存新鲜度验证的 ETag
    long serverDate Http 响应首部中的响应产生时间
    long ttl 缓存的过期时间
    long softTtl 缓存的新鲜时间
    Map<String, String> responseHeaders 响应的 Headers
    boolean isExpired() 判断缓存是否过期,过期缓存不能继续使用
    boolean refreshNeeded() 判断缓存是否新鲜,不新鲜的缓存需要发到服务端做新鲜度的检测
    4.2.7 DiskBasedCache.java

    继承 Cache 类,基于 Disk 的缓存实现类。
    (1). 主要方法:

    public synchronized void initialize() 初始化,扫描缓存目录得到所有缓存数据摘要信息放入内存。
    public synchronized Entry get(String key) 从缓存中得到数据。先从摘要信息中得到摘要信息,然后读取缓存数据文件得到内容。
    public synchronized void put(String key, Entry entry) 将数据存入缓存内。先检查缓存是否会满,会则先删除缓存中部分数据,然后再新建缓存文件。
    private void pruneIfNeeded(int neededSpace) 检查是否能再分配 neededSpace 字节的空间,如果不能则删除缓存中部分数据。
    public synchronized void clear() 清空缓存。 public synchronized void remove(String key) 删除缓存中某个元素。

    (2). CacheHeader 类
    CacheHeader 是缓存文件摘要信息,存储在缓存文件的头部,与上面的Cache.Entry相似。

    4.2.8 NoCache.java

    继承 Cache 类,不做任何操作的缓存实现类,可将它作为构建RequestQueue的参数以实现一个不带缓存的请求队列。

    4.2.9 Network.java

    代表网络的接口,处理网络请求。
    唯一的方法,用于执行特定请求。

    public NetworkResponse performRequest(Request<?> request) throws VolleyError;
    4.2.10 NetworkResponse.java

    Network中方法 performRequest 的返回值,Request的 parseNetworkResponse(…) 方法入参,是 Volley 中用于内部 Response 转换的一级。
    封装了网络请求响应的 StatusCode,Headers 和 Body 等。
    (1). 成员变量

    int statusCode Http 响应状态码
    byte[] data Body 数据
    Map<String, String> headers 响应 Headers
    boolean notModified 表示是否为 304 响应
    long networkTimeMs 请求耗时

    (2). Volley 的内部 Response 转换流程图
    这里写图片描述
    从上到下表示从得到数据后一步步的处理,箭头旁的注释表示该步处理后的实体类。

    4.2.11 BasicNetwork.java

    实现 Network,Volley 中默认的网络接口实现类。调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
    主要实现了以下功能:
    (1). 利用 HttpStack 执行网络请求。
    (2). 如果 Request 中带有实体信息,如 Etag,Last-Modify 等,则进行缓存新鲜度的验证,并处理 304(Not Modify)响应。
    (3). 如果发生超时,认证失败等错误,进行重试操作,直到成功、抛出异常(不满足重试策略等)结束。

    4.2.12 HttpStack.java

    用于处理 Http 请求,返回请求结果的接口。目前 Volley 中的实现有基于 HttpURLConnection 的 HurlStack 和 基于 Apache HttpClient 的 HttpClientStack。
    唯一方法,执行请求

    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError;

    执行 Request 代表的请求,第二个参数表示发起请求之前,添加额外的请求 Headers。

    4.2.13 HttpClientStack.java

    实现 HttpStack 接口,利用 Apache 的 HttpClient 进行各种请求方式的请求。
    基本就是 org.apache.http 包下面相关类的常见用法,不做详解,不过与下面 HttpURLConnection 做下对比就能发现 HttpURLConnection 的 API 相对简单的多。

    4.2.14 HurlStack.java

    实现 HttpStack 接口,利用 Java 的 HttpURLConnection 进行各种请求方式的请求。

    4.2.15 Response.java

    封装了经过解析后的数据,用于传输。并且有两个内部接口 Listener 和 ErrorListener 分别可表示请求失败和成功后的回调。
    Response 的构造函数被私有化,而通过两个函数名更易懂的静态方法构建对象。

    4.2.16 ByteArrayPool.java

    byte[] 的回收池,用于 byte[] 的回收再利用,减少了内存的分配和回收。 主要通过一个元素长度从小到大排序的ArrayList作为 byte[] 的缓存,另有一个按使用时间先后排序的ArrayList属性用于缓存满时清理元素。

    public synchronized void returnBuf(byte[] buf)

    将用过的 byte[] 回收,根据 byte[] 长度按照从小到大的排序将 byte[] 插入到缓存中合适位置。

    public synchronized byte[] getBuf(int len)

    获取长度不小于 len 的 byte[],遍历缓存,找出第一个长度大于传入参数len的 byte[],并返回;如果最终没有合适的 byte[],new 一个返回。

    private synchronized void trim()

    当缓存的 byte 超过预先设置的大小时,按照先进先出的顺序删除最早的 byte[]。

    4.2.17 PoolingByteArrayOutputStream.java

    继承 ByteArrayOutputStream,原始 ByteArrayOutputStream 中用于接受写入 bytes 的 buf,每次空间不足时便会 new 更大容量的 byte[],而 PoolingByteArrayOutputStream 使用了 ByteArrayPool 作为 Byte[] 缓存来减少这种操作,从而提高性能。

    4.2.18 HttpHeaderParser.java

    Http header 的解析工具类,在 Volley 中主要作用是用于解析 Header 从而判断返回结果是否需要缓存,如果需要返回 Header 中相关信息。
    有三个方法

    public static long parseDateAsEpoch(String dateStr)
    解析时间,将 RFC1123 的时间格式,解析成 epoch 时间
    public static String parseCharset(Map<String, String> headers)
    解析编码集,在 Content-Type 首部中获取编码集,如果没有找到,默认返回 ISO-8859-1
    public static Cache.Entry parseCacheHeaders(NetworkResponse response)
    比较重要的方法,通过网络响应中的缓存控制 Header 和 Body 内容,构建缓存实体。如果 HeaderCache-Control 字段含有no-cache或no-store表示不缓存,返回 null

    (1). 根据 Date 首部,获取响应生成时间
    (2). 根据 ETag 首部,获取响应实体标签
    (3). 根据 Cache-Control 和 Expires 首部,计算出缓存的过期时间,和缓存的新鲜度时间
    两点需要说明下:
    1.没有处理Last-Modify首部,而是处理存储了Date首部,并在后续的新鲜度验证时,使用Date来构建If-Modified-Since。 这与 Http 1.1 的语义有些违背。
    2.计算过期时间,Cache-Control 首部优先于 Expires 首部。

    4.2.19 RetryPolicy.java

    重试策略接口
    有三个方法:

    public int getCurrentTimeout();
    获取当前请求用时(用于 Log)
    public int getCurrentRetryCount();
    获取已经重试的次数(用于 Log)
    public void retry(VolleyError error) throws VolleyError;
    确定是否重试,参数为这次异常的具体信息。在请求异常时此接口会被调用,可在此函数实现中抛出传入的异常表示停止重试。
    4.2.20 DefaultRetryPolicy.java

    实现 RetryPolicy,Volley 默认的重试策略实现类。主要通过在 retry(…) 函数中判断重试次数是否达到上限确定是否继续重试。
    其中mCurrentRetryCount变量表示已经重试次数。
    mBackoffMultiplier表示每次重试之前的 timeout 该乘以的因子。
    mCurrentTimeoutMs变量表示当前重试的 timeout 时间,会以mBackoffMultiplier作为因子累计前几次重试的 timeout。

    4.2.21 ResponseDelivery.java

    请求结果的传输接口,用于传递请求结果或者请求错误。
    有三个方法:

    public void postResponse(Request<?> request, Response<?> response);
    此方法用于传递请求结果,requestresponse 参数分别表示请求信息和返回结果信息。
    public void postResponse(Request<?> request, Response<?> response, Runnable runnable);
    此方法用于传递请求结果,并在完成传递后执行 Runnable。
    public void postError(Request<?> request, VolleyError error);
    此方法用于传输请求错误。
    4.2.22 ExecutorDelivery.java

    请求结果传输接口具体实现类。
    在 Handler 对应线程中传输缓存调度线程或者网络调度线程中产生的请求结果或请求错误,会在请求成功的情况下调用 Request.deliverResponse(…) 函数,失败时调用 Request.deliverError(…) 函数。

    4.2.23 StringRequest.java

    继承 Request 类,代表了一个返回值为 String 的请求。将网络返回的结果数据解析为 String 类型。通过构造函数的 listener 传参,支持请求成功后的 onResponse(…) 回调。

    4.2.24 JsonRequest.java

    抽象类,继承自 Request,代表了 body 为 JSON 的请求。提供了构建 JSON 请求参数的方法。

    4.2.25 JsonObjectRequest.java

    继承自 JsonRequest,将网络返回的结果数据解析为 JSONObject 类型。

    4.2.26 JsonArrayRequest.java

    继承自 JsonRequest,将网络返回的结果数据解析为 JSONArray 类型。

    4.2.27 ImageRequest.java

    继承 Request 类,代表了一个返回值为 Image 的请求。将网络返回的结果数据解析为 Bitmap 类型。
    可以设置图片的最大宽度和最大高度,并计算出合适尺寸返回。每次最多解析一张图片防止 OOM。

    4.2.28 ImageLoader.java

    封装了 ImageRequst 的方便使用的图片加载工具类。
    1.可以设置自定义的ImageCache,可以是内存缓存,也可以是 Disk 缓存,将获取的图片缓存起来,重复利用,减少请求。
    2.可以定义图片请求过程中显示的图片和请求失败后显示的图片。
    3.相同请求(相同地址,相同大小)只发送一个,可以避免重复请求。
    // TODO

    4.2.29 NetworkImageView.java

    利用 ImageLoader,可以加载网络图片的 ImageView
    有三个公开的方法:

    public void setDefaultImageResId(int defaultImage)
    设置默认图片,加载图片过程中显示。
    public void setErrorImageResId(int errorImage)
    设置错误图片,加载图片失败后显示。
    public void setImageUrl(String url, ImageLoader imageLoader)
    设置网络图片的 Url 和 ImageLoader,将利用这个 ImageLoader 去获取网络图片。
    如果有新的图片加载请求,会把这个 ImageView 上旧的加载请求取消。
    4.2.30 ClearCacheRequest.java

    用于人为清空 Http 缓存的请求。
    添加到 RequestQueue 后能很快执行,因为优先级很高,为Priority.IMMEDIATE。并且清空缓存的方法mCache.clear()写在了isCanceled()方法体中,能最早的得到执行。
    ClearCacheRequest 的写法不敢苟同,目前看来唯一的好处就是可以将清空缓存操作也当做一个请求。而在isCanceled()中做清空操作本身就造成了歧义,不看源码没人知道在NetworkDispatcher run 方法循环的过程中,isCanceled()这个读操作竟然做了可能造成缓存被清空。只能跟源码的解释一样当做一个 Hack 操作。

    总结(可以学习的地方):
    1. 兼容性好:默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现 (android 2.3以下HttpURLConnection有严重bug)
    2. 提供了取消Http 请求的接口,在Activity关闭但是仍旧执行的Http请求可以及时销毁,减少了性能的开销以及Activity能够及时回收。
    3. 使用了多线程(默认4个线程)+ 请求队列的形式,而不是每次请求都单独开启一个线程,减少了性能的开销。
    4. 支持缓存:在Http协议层(在进行条件请求时,客户端会提供给服务器一个If-Modified-Since请求头,其值为服务器上次返回的Last-Modified响应头中的日期值, 服务器会读取到这两个请求头中的值,判断出客户端缓存的资源是否是最新的,如果是的话,服务器就会返回HTTP/304 Not Modified响应)和客户端都支持cache,大大减少了服务器压力。同时对客户端性能开销也会有一定的减少。
    5. 避免同一个http请求多次连接服务器:如果某个请求已经在等待队列,并且该请求允许缓存,将该请求放到等待队列中,使得URI一致的请求不会重复去请求服务器.
    6. 从框架本身的角度来说,Request接口、Cache接口、HttpStack等都是以接口的形式来定义的,充分地展示了Java中面向接口编程的特点,使得代码的扩展性大大增强

    5. 注意事项

    Volley 适合于数据量小的并发请求,因为在数据请求完成后,会将请求得到的数据读到内存中存放在byte[],然后分发给调用者进行数据的转换。若用volley请求大数据则可能会OOM。
    Volley的线程池不具备伸缩功能,创建后所有线程均处于启用状态,不支持动态调整。

    展开全文
  • android.httpAsnc 安卓网络请求工具
  • broid Broid 是一个轻量级的Android开发工具包 可以简化持久化存储以及异步请求网络的开发
  • 1.首先先介绍一个概念dispatch_semaphore dispatch_semaphore信号量为基于计数器的一种多线程同步机制。用于解决在多个线程访问共有资源时候,会因为多线程...5.至此解决了依次执行异步网络请求 的一种实现方法

    1.首先先介绍一个概念dispatch_semaphore


    • dispatch_semaphore信号量为基于计数器的一种多线程同步机制。用于解决在多个线程访问共有资源时候,会因为多线程的特性而引发数据出错的问题.
    • 如果semaphore计数大于等于1,计数-1,返回,程序继续运行。如果计数为0,则等待。
    • dispatch_semaphore_signal(semaphore)为计数+1操作。dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)为设置等待时间,这里设置的等待时间是一直等待。我们可以通俗的理解为单柜台排队点餐,计数默认为0,每当有顾客点餐,计数+1,点餐结束-1归零继续等待下一位顾客。比较类似于NSLock。

    2.主要是介绍使用dispatch_semaphore和NSOperationQueue结合实现依次执行异步请求


    • NSOperationQueue中装有任务,设置任务之间相互依赖
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ 
        [self request:@”A”]; 
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        [self request:@"B"];
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{ 
        [self request:@”C”]; 
    }];
    [operation2 addDependency:operation1]; //任务二依赖任务一 
    [operation3 addDependency:operation2]; //任务三依赖任务二
    • 将任务加入队列中
    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    
    [queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO]; 
    • 测试执行顺序并非是按照A-B-C依赖执行,并且无法得知何时任务执行完毕,进行下一步操作.下面解决这两个问题

    3.解决如何依次执行.就要用到开头介绍的:dispatch_semaphore来限制是否执行

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //默认创建的信号为0
    
    [[NetworkManager shared] RequestWithMethod:HttpMethod_POST Url:strURL params:params success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"%@",index);
        dispatch_semaphore_signal(semaphore); //这里请求成功信号量 +1 为1
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        dispatch_semaphore_signal(semaphore); //这里请求失败信号量 +1 为1
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //走到这里如果信号量为0 则不再执行下面的代码 一直等待 信号量不是0 出现 才会执行下面代码,然后信号量为 - 1
    
    • 这个解决了依次执行的问题 下面解决怎么知道全部执行完毕呢

    4. 执行完毕问题的解决,使用KVO监听任务数是否为0

    //添加监听 监听队列是否全部执行完毕
    [queue addObserver:self forKeyPath:@"operationCount" options:0 context:nil];
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    if ([keyPath isEqualToString:@"operationCount"]) {
        NSOperationQueue *queue = (NSOperationQueue *)object;
        if (queue.operationCount == 0) {
            NSLog(@"全部完成");
        }
    }
    }

    5.至此解决了依次执行异步网络请求 的一种实现方法

    展开全文
  • iOS 同步异步网络请求

    2015-04-08 13:13:13
    iOS POST GET 同步 异步 网络请求
  • 主要介绍了Android HTTP网络请求异步实现,感兴趣的小伙伴们可以参考一下
  • android异步网络请求工具库,此jar包中附带了源码,可以查看源码了解工作原理。
  • 异步网络请求

    2014-07-29 16:41:55
    异步网络请求工具,简单实用,开发效率提高
  • 《android网络请求框架》一个轻量级的异步网络请求框架MyHttpUtils(新版更新记录,版本号:2.X)一、前言基本的用法在《Android网络请求篇》MyHttpUtils一个非常好用的异步网络请求框架中有过详细的介绍。...
  • 《Android网络请求篇》MyHttpUtils一个非常好用的异步网络请求框架一、能做什么 你只需要传url,JavaBean就可以在回调方法里面得到想要的结果,你会发现你的代码里面没有了子线程、没有了handle,链式的变成使得...
  • swift3 多个异步网络请求转同步

    千次阅读 2017-03-24 23:18:30
    场景在开发过程中很常见的一个场景是一个页面需要调用两个异步网络请求,需要等两个请求都返回以后再组合数据并刷新UI, 流程如下:graph TD A[client] --> B(Request) B --> |One| C[Http request 1] B --> |...
  • 由于目前的Android已经不允许在UI线程中进行网络请求了,所以现在进行网络请求等较为耗时的操作都需要开辟新的线程来运行。否则有可能会造成ANR错误。而Asynctask便是解决这个问题的一种方法。 在源码中注释对...
  • 今天给大家分享一个github上Top1的Android异步网络请求框架的使用方法,我给大家分享一个它的基本用法。 先来一个简单的get请求 AsyncHttpClient client = new AsyncHttpClient(); client.get(...
  • Flutter通过FutureBuilder实现异步请求网络数据并显示加载中Demo,详情请看博客Flutter中的异步(Future、async、await、FutureBuilder)和 网络请求:https://yuzhiqiang.blog.csdn.net/article/details/89155870
  • 异步回调网络请求

    2017-11-29 18:36:09
    以前开发Android,与很多地方需要用到异步网络请求,当然这方面很多现成的框架可以用,但是B/S上没有发现这类的框架,发送一些请求只能单纯的Http的Get、Post请求。 因为需要,所以自己写了能够异步回掉的网络请求。...
  • 异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕 同步交互,就是最常见的click-refresh模式,点一个连接或提交一个表单,然后整个页面被刷新 异步交互,当前很热的AJAX就是...
  • 小程序开发-网络请求异步问题

    千次阅读 2018-11-21 18:07:46
    大家都知道网络操作的响应时间是不定的,所有的网络操作是异步操作,当我们需要请求按照我们所希望的顺序来执行时,就需要进行一些处理,可以将请求做成串行的(这种方式还未了解具体怎么实现),这里记录另外一种...
  • 场景:某日面试的时候被问道,Retrofit异步网络请求是怎么把结果返回给主线程的? 答曰:具体原理不是很清楚,最后应该是通过handler把结果发送到主线程的吧。。。 问:你确定吗?真是handler吗? 这一问把我问懵...
  • java怎么实现异步请求网络,这里实现思路有很多种,但是我们这里有个比较方便的请求方式就是。如下代码; List<List<String>>tempList=Arr...
  • 最近很流行RxJava+OkHttp; 我想问的是,目前大部分网络框架中的都有异步网络请求的方法,为什么非得配合Rxjava去进行异步操作呢?
  • 串行异步网络请求的简单实现

    千次阅读 2016-05-06 13:33:01
    转载于:http://code4cocoa.com/2016/02/21/串行异步网络请求的简单实现/ ...实质上这就是一个串行异步网络请求的过程(串行执行一个异步任务序列)。 方案一 使用递归实现,网络请求部分我这里使用AFNetworking,当然
  • IOS 异步 网络请求

    千次阅读 2014-01-09 17:02:03
    1、发送异步的GET请求 2、发送异步的POST请求

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 289,822
精华内容 115,928
关键字:

异步网络请求