SaveVolley

Save volley from anything, By Agera to save. Thus, derived the AgeraVolley . (。>﹏<。)

Language License Version Download Build Status

gson: 2.7

fastjson: 1.1.52.android

agera: 1.1.0

okhttp3: 3.3.1


savevolley-okhttp3-agera-gson || savevolley-okhttp3-agera-fastjson

savevolley-okhttp3-agera-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.google.android.agera:agera:1.1.0'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-okhttp3-agera-gson:1.6.6'
}

可以使用 SaveVolley Flowagera Flow

    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(GSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories.repositoryWithInitialValue(
        INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });

savevolley-okhttp3-agera-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.google.android.agera:agera:1.1.0'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-okhttp3-agera-fastjson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(FASTJSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories
        .repositoryWithInitialValue(INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });


savevolley-hurl-agera-gson || savevolley-hurl-agera-fastjson

可以使用 SaveVolley Flowagera Flow

savevolley-hurl-agera-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.google.android.agera:agera:1.1.0'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-hurl-agera-gson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(GSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories.repositoryWithInitialValue(
        INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });

savevolley-hurl-agera-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'
    compile 'com.google.android.agera:agera:1.1.0'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-hurl-agera-fastjson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(FASTJSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories
        .repositoryWithInitialValue(INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });


savevolley-okhttp3-gson || savevolley-okhttp3-fastjson

savevolley-okhttp3-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-okhttp3-gson:1.6.6'
}

可以使用 OkHttp3GsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new OkHttp3GsonRequest<GankData>(TEST_URL,
        GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }

        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(Okhttp3GsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });

savevolley-okhttp3-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-okhttp3-fastjson:1.6.6'
}

可以使用 Okhttp3FastjsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new OkHttp3FastjsonRequest<GankData>(TEST_URL, GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }

        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(Okhttp3FastjsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });


savevolley-hurl-gson || savevolley-hurl-fastjson

savevolley-hurl-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-hurl-gson:1.6.6'
}

可以使用 HurlGsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new HurlGsonRequest<GankData>(TEST_URL,
        GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }

        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(HurlGsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });

savevolley-hurl-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-hurl-fastjson:1.6.6'
}

可以使用 HurlFastjsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new HurlFastjsonRequest<GankData>(TEST_URL, GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }

        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(HurlFastjsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });


savevolley-okhttp3

gradle

dependencies {
    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
}

savevolley-okhttp3

将 原版的 google/volley 中 网络实现层 的 Apache HttpClient原生的 HttpUrlConnection 都移除。 换成 square/okhttp3 作为实现网络请求。


savevolley-hurl

gradle

dependencies {
    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
}

API >= 9

savevolley-hurl

移除了 原版 google/volley 中的,所有相关与 HttpClient 的逻辑,全版本的网络通信接入到 HttpUrlConnection 内。


savevolley-network-core

savevolley-network-core

由于,网络底层实现( 网络请求实现 )可以通过不同框架( okhttp、HttpUrlConnection、Apache HttpClient ... )去实现。
所以,只是拿到 不同框架的响应结果
但是 Volley 的缓存层是 通用的,所以需要定义一套 通用的 HTTP Response API,然后将 不同框架的响应结果 转换为
通用的 HTTP Response API

这个模块还需要与 savevolley-network-adapter 的子模块( savevolley-network-okhttp3-adapter, savevolley-network-hurl-adapter )一起协作。


savevolley-network-adapter

savevolley-network-adapter

目的是为了定义一些接口: 不同框架的响应结果 >> 通用的 HTTP Response API
子模块有: savevolley-network-okhttp3-adapter, savevolley-network-hurl-adapter


savevolley-network-okhttp3-adapter

savevolley-network-okhttp3-adapter

savevolley-network-adapter 的子模块,square/okhttp Response >> 通用的 HTTP Response API


savevolley-network-hurl-adapter

savevolley-network-hurl-adapter

savevolley-network-adapter 的子模块,HttpConnection >> 通用的 HTTP Response API


extensions / savevolley-hurl-agera-core

savevolley-hurl-agera-core

作用: 提供一些 hurlagera 协作需要的基础类。


extensions / savevolley-okhttp3-agera-core

savevolley-okhttp3-agera-core

作用: 提供一些 okhttp3agera 协作需要的基础类。


extensions / agera-gson / savevolley-okhttp3-agera-gson

savevolley-okhttp3-agera-gson

作用: agera >> savevolley-okhttp3 << gson , 为 savevolley-okhttp3 桥接了 ageragson


extensions / agera-gson / savevolley-hurl-agera-gson

savevolley-hurl-agera-gson

作用: agera >> savevolley-hurl << gson , 为 savevolley-hurl 桥接了 ageragson


extensions / agera-fastjson / savevolley-okhttp3-agera-fastjson

savevolley-okhttp3-agera-fastjson

作用: agera >> savevolley-okhttp3 << fastjson , 为 savevolley-okhttp3 桥接了 agerafastjson


extensions / agera-fastjson / savevolley-hurl-agera-fastjson

savevolley-hurl-agera-fastjson

作用: agera >> savevolley-hurl << fastjson , 为 savevolley-hurl 桥接了 agerafastjson


extensions / fastjson / savevolley-hurl-fastjson

savevolley-hurl-fastjson

作用: fastjson >> savevolley-hurl


extensions / fastjson / savevolley-okhttp3-fastjson

savevolley-okhttp3-fastjson

作用: fastjson >> savevolley-okhttp3


extensions / gson / savevolley-hurl-gson

savevolley-hurl-gson

作用: gson >> savevolley-hurl


extensions / gson / savevolley-okhttp3-gson

savevolley-okhttp3-gson

作用: gson >> savevolley-okhttp3


square-okhttp3

square/okhttp Version: 3.3.1


google-agera

google/agera Version: 1.1.0-beta2



volley-comments

volley-comments

原版的 google/volley,全部代码加上了注释。

入口

Volley:Volley 框架使用的入口,用于创建一个 RequestQueue。

RequestQueueRequestQueue 被定义为 请求队列。用于操作 缓存请求执行线程( CacheDispatcher )和 网络请求执行线程( NetworkDispatcher )。默认的情况下:

核心 异步

NetworkDispatcher:是用于处理 Volley 中的网络请求 的 网络线程,会将 网络 Request 队列的 Request 逐个抽出,然后进行网络请求:

CacheDispatcher:是用于处理 Volley 中的缓存数据 的 缓存线程

网络请求 使用层

Network:在 Volley 中,是处理 网络请求 的表层使用接口。只有一个方法:performRequest(...) 执行请求,

BasicNetworkBasicNetwork 是 目前 Volley 内,Network 接口的唯一实现类,在 Volley 内,处理了 网络请求 的表层使用接口。实现了 performRequest(...) 方法的具体功能,performRequest(...) 要做的事情是

网络请求 实现层

HttpStackHttpStack 是 Volley 内 执行 网络请求 的 底层实现接口。实现类有:

HttpClientStackHttpClientStack 实现了 HttpStack 接口。封装了基于 org.apache.http.HttpClient 提供的网络实现( performRequest(...) ),处理了 2.3 版本以下的 各种网络请求( GET、POST、DEL ... )的实现

HurlStackHurlStack 实现了 HttpStack 接口。封装了基于 javax.net.ssl.HttpsURLConnection 提供的网络实现( performRequest(...) ),处理了 2.3 版本以上的 各种网络请求( GET、POST、DEL ... )的实现

请求( Request )

Request:Volley 内所有抽象请求的 基类

StringRequest:继承扩展了 Request,指定了泛型为 <String>。会将请求结果解析成 String 类型数据,并且 需要你 传入一个 Response.Listener<String> 进行解析结果数据进行回调。

JsonRequestJsonRequest<T> 抽象继承了 Request<T> 类。

JsonObjectRequestJsonObjectRequest 继承自 JsonRequest<JSONObject>,将 JsonRequest<T> 的泛型 T,设置为 JSONObjectJsonRequest<T> 没有解析 body 内的数据为 真正的 Json 数据。所以,JsonObjectRequest 要单独将 body 内的数据解析为 JSONObject类型。

JsonArrayRequestJsonArrayRequest 继承自 JsonRequest<JSONArray>,将 JsonRequest<T> 的泛型 T,设置为 JSONArrayJsonRequest<T> 没有解析 body 内的数据为 真正的 Json 数据。所以,JsonArrayRequest 要单独将 body 内的数据解析为 JSONArray 类型。

ImageRequest:继承扩展了 Request,指定了泛型为 <Bitmap>,会将请求结果解析成 Bitmap 类型数据。并且需要你传入:

ClearCacheRequestClearCacheRequest 继承自 Request<Object>,用于清空 HTTP 缓存的请求。如果该请求被添加到 请求队列( RequestQueue )中,由于覆写了 getPriority() 方法,将优先级设置为 Priority.IMMEDIATE ( 立即执行 )

响应( Response )

Response:请求结果(响应)类。

缓存

Cache:Volley 缓存的接口。提供一些接口方法,需要子类去实现,全 Volley 中主要实现类,只有一个 DiskBasedCache

DiskBasedCacheDiskBasedCacheCache 的实现类。用于将保存缓存文件在硬盘上的指定目录中,默认的缓存大小是 5MB,缓存大小是可以手动配置的。

NoCache:继承了 Cache,不做任何操作的缓存实现类。可以作为 RequestQueue 构造方法的参数,实现一个不带缓存的请求队列。

数据传递(分发)

ResponseDeliveryResponseDelivery 接口的作用 -> 从 内存缓存 或者 服务器 取得请求结果数据,由 ResponseDelivery 去做结果分发以及回调处理。

ExecutorDeliveryExecutorDelivery 实现了 ResponseDelivery 接口。 主要功能就是:

构造方法也是有趣设计:

工具

HttpHeaderParserHttp header 的解析工具类。

RequestFutureRequestFuture<T> 实现了 Future<T> 接口,用于对 Request 解析数据的结果 进行 取消查询是否完成获取结果

byte[] 流和缓存池

ByteArrayPool:一个 byte[] 缓存池,用于 byte[] 的回收再利用,减少内存分配和回收。

PoolingByteArrayOutputStreamPoolingByteArrayOutputStream 继承了 原生的 ByteArrayOutputStream,使用了 ByteArrayPool 回收利用一些 byte[],防止了 byte[] 的重复内存分配和回收。

重试策略

RetryPolicy:重试策略接口。具体实现可以自定义,也有默认的 DefaultRetryPolicy

DefaultRetryPolicyDefaultRetryPolicy 继承自 RetryPolicy注意的地方就是 -> mBackoffMultiplierDEFAULT_BACKOFF_MULT 用于设置 退避乘数,跟 "指数退避" 有关。

日志

VolleyLogVolleyLog 是 Volley 的一个工具类。根据 Log.isLoggable(String tag,int level) 设置 Log 的开关。 level >= INFOisLoggable 返回 true,反之则返回 false,所以,开关 默认 关闭。

MarkerLog:VolleyLog 提供的一个简单的静态内部 Log 类。可以通过 add(...) 添加一个 MarkerLog 的 Log 单位( Marker ),然后调用 finish(...) 打印已经添加的所有 Log。

认证

Authenticator:一个身份认证接口,用于基本认证或者摘要认证。在 Volley 内,是用于和身份认证,比如 OAuth。

AndroidAuthenticator:实现了 Authenticator 接口,基于 Android 上的 AccountManager,实现了认证交互。

错误类型

VolleyError:所有 Volley 错误的基类。继承自 Exception,用于描述 Volley 中所有的错误异常,可以设置 NetworkResponse 和 请求消耗时间。

AuthFailureErrorAuthFailureError 继承了 VolleyError。表示:请求认证失败错误,如 RespondCode 的 401 和 403

TimeoutErrorTimeoutError 继承了 VolleyError。表示:请求超时错误。但是什么都没有实现,作为一个标识存在。

ServerErrorServerError 继承了 VolleyError。表示:服务端错误

ClientErrorClientError 扩展了 ServerError 的概念。表示:客户端错误,即 4xx 错误

ParseErrorParseError 继承了 VolleyError。表示:内容解析错误

NoConnectionErrorNoConnectionError 继承了 NetworkError。表示:网络连接错误

NetworkErrorNetworkError 继承了 VolleyError,表示:网络错误



License

  Copyright (C) 2016 CaMnter [email protected]
  Copyright (C) 2015 Google Inc. All Rights Reserved.
  Copyright (C) 2012 Square, Inc.
  Copyright (C) 2011 The Android Open Source Project
  Copyright (C) 2008 The Apache Software Foundation (ASF)
  Copyright (C) 2007 The Guava Authors

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.