├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── hadcn │ │ └── davinci_example │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── hadcn │ │ │ └── davinci_example │ │ │ ├── ListActivity.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ ├── activity_list.xml │ │ ├── activity_main.xml │ │ └── item_image.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── hadcn │ └── davinci_example │ └── ExampleUnitTest.java ├── build.gradle ├── davinci ├── .gitignore ├── build.gradle ├── libs │ └── httpmime-4.1.3.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── hadcn │ │ └── davinci │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── hadcn │ │ └── davinci │ │ ├── DaVinci.java │ │ ├── base │ │ └── VolleyManager.java │ │ ├── http │ │ ├── OnDaVinciRequestListener.java │ │ ├── base │ │ │ └── StringRequest.java │ │ └── impl │ │ │ ├── HttpRequest.java │ │ │ ├── PersistentCookieStore.java │ │ │ └── SerializableHttpCookie.java │ │ ├── image │ │ ├── ReadImageTask.java │ │ ├── VinciImageLoader.java │ │ ├── VolleyImageListener.java │ │ ├── base │ │ │ ├── ByteRequest.java │ │ │ ├── ImageEntity.java │ │ │ ├── ImageLoader.java │ │ │ └── Util.java │ │ └── cache │ │ │ ├── DiskLruCache.java │ │ │ ├── DiskLruImageCache.java │ │ │ ├── LruCache.java │ │ │ ├── LruImageCache.java │ │ │ └── StrictLineReader.java │ │ ├── other │ │ ├── OnVinciDownloadListener.java │ │ ├── OnVinciUploadListener.java │ │ ├── impl │ │ │ ├── VinciDownload.java │ │ │ └── VinciUpload.java │ │ └── request │ │ │ └── UploadRequest.java │ │ └── volley │ │ ├── AuthFailureError.java │ │ ├── Cache.java │ │ ├── CacheDispatcher.java │ │ ├── ClientError.java │ │ ├── DefaultRetryPolicy.java │ │ ├── ExecutorDelivery.java │ │ ├── Network.java │ │ ├── NetworkDispatcher.java │ │ ├── NetworkError.java │ │ ├── NetworkResponse.java │ │ ├── NoConnectionError.java │ │ ├── ParseError.java │ │ ├── Request.java │ │ ├── RequestQueue.java │ │ ├── Response.java │ │ ├── ResponseDelivery.java │ │ ├── RetryPolicy.java │ │ ├── ServerError.java │ │ ├── TimeoutError.java │ │ ├── VolleyError.java │ │ └── toolbox │ │ ├── AndroidAuthenticator.java │ │ ├── Authenticator.java │ │ ├── BasicNetwork.java │ │ ├── ByteArrayPool.java │ │ ├── ClearCacheRequest.java │ │ ├── DiskBasedCache.java │ │ ├── HttpHeaderParser.java │ │ ├── HttpStack.java │ │ ├── HurlStack.java │ │ ├── ImageLoader.java │ │ ├── ImageRequest.java │ │ ├── NoCache.java │ │ ├── PoolingByteArrayOutputStream.java │ │ └── RequestFuture.java │ └── res │ ├── drawable │ ├── image_load_error.png │ └── image_loading.png │ └── values │ └── strings.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /local.properties 2 | /.gradle 3 | /.idea 4 | .DS_Store 5 | /build 6 | /captures 7 | /app/*.iml 8 | *.iml 9 | gradle.properties 10 | /davinci/*.iml 11 | /davinci/build 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://jitpack.io/v/CPPAlien/DaVinci.svg)](https://jitpack.io/#CPPAlien/DaVinci) 2 | # DaVinci 3 | 基于Volley实现的一款多功能网络库, 目前包括了普通图片和Gif图片的加载显示、图片的二级缓存机制、可以开启Cookie的http请求等功能。 4 | 5 | **我们先来一张Glide与DaVinci加载同一张网络上Gif图的对比效果** 6 | 7 |
8 | 9 |
10 | 11 | [Demo Download](http://cdn.flowergo.xyz/davinci_demo.apk) 12 | 13 | 从上面我们可以明显看出,Glide加载一张Gif图比DaVinci明显花更久的时间。并且再看加载后的动画效果,DaVinci加载后的Gif图动画非常流畅,而Glide加载过后的Gif的动画有些显示问题。并且用DaVinci加载图片,你可以定制loading过程的图片,而Glide无法做到。 14 | 15 | 我们再来看下实现上述功能,两者需要的代码对比。 16 | 17 | #### DaVinci 18 | ``` 19 | DaVinci 20 | .with(this) 21 | .getImageLoader() 22 | .load("http://7xlkhg.com2.z0.glb.qiniucdn.com/qbi_cry.gif") 23 | .into(image1); 24 | ``` 25 | 26 | #### Glide 27 | ``` 28 | Glide 29 | .with(this) 30 | .load("http://7xlkhg.com2.z0.glb.qiniucdn.com/qbi_cry.gif") 31 | .into(image2); 32 | ``` 33 | 34 | 实现方式基本差不多,但你要知道本库可不单单只有图片加载功能哦。 35 | 36 | 37 | ### 1,特色 38 | 39 | 1,支持Gif图片,并且做到Gif库可插拔; 40 | 41 | 2,实现客户端Http请求的Cookie机制,只要调用一个enable方法就搞定; 42 | 43 | 3,支持内存和本地的二级缓存,让图片加载更加流畅; 44 | 45 | 4, 支持使用POST方法获得图片; 46 | 47 | 5, 支持创建多线程池 48 | 49 | 6, 支持上传、下载功能 50 | 51 | ### 2, 使用方法 52 | 53 | 用Gradle的方式导入DaVinci库,因为DaVinci的日志打印采用[VinciLog](https://github.com/CPPAlien/VinciLog),所以需要同时引入VinciLog库 54 | 55 | ``` 56 | repositories{ 57 | maven { url "https://jitpack.io" } 58 | } 59 | dependencies { 60 | compile 'com.github.CPPAlien:VinciLog:2.0.1' 61 | compile 'com.github.CPPAlien:DaVinci:1.3.2' 62 | } 63 | ``` 64 | 65 | ### 3, Get和Post请求 66 | ``` 67 | DaVinci.with(Context).getHttpRequest() 68 | doGet(String requestUrl, Map params, OnDaVinciRequestListener requestListener) 69 | doPost(String requestUrl, JSONObject postJsonData, OnDaVinciRequestListener requestListener) 70 | doPost(String requestUrl, String postBodyString, OnDaVinciRequestListener requestListener) 71 | 72 | public interface OnDaVinciRequestListener { 73 | void onDaVinciRequestSuccess(String response); 74 | void onDaVinciRequestFailed(String reason); 75 | } 76 | ``` 77 | 78 | ### 4, 从网络上加载图片 79 | ``` 80 | DaVinci.with(Context).getImageLoader().load("image url put here").into(imageView); 81 | ``` 82 | 83 | 你也可以在into是使用`into(ImageView imageView, int loadingImage, int errorImage)`来设置loading图片,和加载错误时的图片 84 | 85 | 本库Gif图片加载采用koral--实现的[android-gif-drawable](https://github.com/koral--/android-gif-drawable),因为此库底层使用C库进行Gif的编解码,所以效率和显示效果方面都比Glide优秀。 86 | 87 | 开启本库Gif功能,你需要导入`compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.15'`,导入后,加载的图片如果为Gif,则会自动以动图的方式在ImageView里面显示。如果你没有导入该android-gif-drawable库,则Gif图会被当做普通图片处理。 88 | 89 | ### 5,其他用法 90 | 91 | * 如果你不想每次在使用`DaVinci.with(Context)`时都传入`Context`,则你可以在所有调用前先`init`一下,以后只要使用`DaVinci.with()`即可。 92 | ``` 93 | /** 94 | * @param isEnableDebug if open log print 95 | * @param debugTag log tag 96 | * @param context context 97 | */ 98 | DaVinci.init(boolean isEnableDebug, String debugTag, Context context) 99 | ``` 100 | 101 | * 开启Cookie机制,Cookie机制开启后,每次的请求头中都会带有`Cookie`头信息。 102 | ``` 103 | DaVinci.with(Context).enableCookie(); 104 | ``` 105 | * 设置默认的Content-Type (默认是 `application/json`) 和 charset(默认是 `utf-8`,此项可选) 106 | ``` 107 | contentType(String contentType, String charset) 108 | ``` 109 | * 加入请求头 110 | ``` 111 | getHttpRequest().headers(Map headersMap) 112 | ``` 113 | * 设置请求超时时间 114 | ``` 115 | getHttpRequest().timeOut(int timesOutMs) 116 | ``` 117 | 118 | * 设置请求的错误尝试次数 119 | ``` 120 | getHttpRequest().maxRetries(int maxRetries) 121 | ``` 122 | * 设置加载图片大小,下载后图片长宽按比例缩放为设定的maxpix大小,并且使用url + maxPix的方式作为key, 缓存到本地 123 | ``` 124 | getImageLoader().resize(int maxPix).load(...) 125 | ``` 126 | **注:1, 对Gif无效;2, 如果不想使用maxPix作为key的一部分,可以使用resize(int maxPix, 0);** 127 | 128 | * 使用POST方法加载图片,body中为post方法体 129 | ``` 130 | getImageLoader().body(XXXX).load(...) 131 | ``` 132 | 133 | Thanks for DiskLruCache which powered by Jake Wharton. 134 | 135 | https://github.com/JakeWharton/DiskLruCache 136 | 137 | Thanks for Fran Montiel who wrote the PersistentCookieStore(https://gist.github.com/franmontiel/ed12a2295566b7076161) 138 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "cn.hadcn.davinci_example" 9 | minSdkVersion 10 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | repositories { 23 | flatDir { 24 | dirs 'libs' 25 | } 26 | } 27 | 28 | dependencies { 29 | compile project(':davinci') 30 | compile 'com.android.support:appcompat-v7:23.3.0' 31 | compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.15' 32 | compile 'com.github.bumptech.glide:glide:3.7.0' 33 | compile 'com.android.support:recyclerview-v7:23.3.0' 34 | //compile 'com.github.CPPAlien:DaVinci:1.1.9' 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Coding\android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/hadcn/davinci_example/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package cn.hadcn.davinci_example; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/cn/hadcn/davinci_example/ListActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hadcn.davinci_example; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import cn.hadcn.davinci.DaVinci; 16 | 17 | public class ListActivity extends AppCompatActivity { 18 | private ImageAdapter mAdapter; 19 | private List urls = new ArrayList<>(); 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_list); 25 | 26 | RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); 27 | recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 28 | mAdapter = new ImageAdapter(); 29 | recyclerView.setAdapter(mAdapter); 30 | 31 | urls.add("http://e.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494eef42db15f28f5e0fe99257e6c.jpg"); 32 | urls.add("http://e.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494eef42db15f28f5e0fe99257e6c.jpg"); 33 | 34 | mAdapter.notifyDataSetChanged(); 35 | 36 | findViewById(R.id.refresh_button).setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | urls.add(0, "http://g.hiphotos.baidu.com/image/pic/item/54fbb2fb43166d2219dec065442309f79152d292.jpg"); 40 | mAdapter.notifyDataSetChanged(); 41 | } 42 | }); 43 | } 44 | 45 | private class ImageAdapter extends RecyclerView.Adapter { 46 | 47 | @Override 48 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 49 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false); 50 | return new ViewHolder(view); 51 | } 52 | 53 | @Override 54 | public void onBindViewHolder(ViewHolder holder, int position) { 55 | DaVinci.with().getImageLoader().load(urls.get(position)).into(holder.ivImage); 56 | } 57 | 58 | @Override 59 | public int getItemCount() { 60 | return urls.size(); 61 | } 62 | 63 | class ViewHolder extends RecyclerView.ViewHolder { 64 | ImageView ivImage; 65 | 66 | public ViewHolder(View itemView) { 67 | super(itemView); 68 | ivImage = (ImageView)itemView.findViewById(R.id.item_image); 69 | } 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/cn/hadcn/davinci_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.hadcn.davinci_example; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.BitmapDrawable; 6 | import android.os.Environment; 7 | import android.support.v4.content.ContextCompat; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.util.Log; 11 | import android.view.View; 12 | import android.widget.ImageView; 13 | import android.widget.TextView; 14 | 15 | import com.bumptech.glide.Glide; 16 | 17 | import org.json.JSONException; 18 | import org.json.JSONObject; 19 | 20 | import java.io.ByteArrayOutputStream; 21 | import java.io.FileNotFoundException; 22 | import java.io.FileOutputStream; 23 | import java.io.OutputStream; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | import cn.hadcn.davinci.DaVinci; 28 | import cn.hadcn.davinci.log.LogLevel; 29 | import cn.hadcn.davinci.http.OnDaVinciRequestListener; 30 | import cn.hadcn.davinci.log.VinciLog; 31 | import cn.hadcn.davinci.other.OnVinciDownloadListener; 32 | import cn.hadcn.davinci.other.OnVinciUploadListener; 33 | 34 | public class MainActivity extends AppCompatActivity implements OnDaVinciRequestListener { 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_main); 40 | 41 | 42 | DaVinci.init(5, LogLevel.DEBUG, "DaVinciTest", this); 43 | DaVinci.with(this).enableCookie(); 44 | 45 | VinciLog.e(null, "a"); 46 | VinciLog.e("test %d, test %s", 1, "a"); 47 | VinciLog.e("test %d, test %s", "a", "a"); 48 | 49 | ImageView image1 = (ImageView)findViewById(R.id.image1); 50 | ImageView image2 = (ImageView)findViewById(R.id.image2); 51 | ImageView image3 = (ImageView)findViewById(R.id.image3); 52 | DaVinci.with(this).getImageLoader().load("http://7xlkhg.com2.z0.glb.qiniucdn.com/qbi_cry.gif").into(image1); 53 | 54 | Glide.with(this).load("http://7xlkhg.com2.z0.glb.qiniucdn.com/qbi_cry.gif").into(image2); 55 | DaVinci.with(this).getImageLoader().load("http://photo.enterdesk.com/2011-11-26/enterdesk.com-1CB20FDF5918603F9264E5BFDC4DF691.jpg").resize(400).into(image3); 56 | image2.setOnClickListener(new View.OnClickListener() { 57 | @Override 58 | public void onClick(View view) { 59 | DaVinci.with(MainActivity.this).getHttpRequest().doGet("http://www.baidu.com/", null, null); 60 | } 61 | }); 62 | 63 | Map map = new HashMap<>(); 64 | map.put("q", "Beijing,cn"); 65 | map.put("appid", "2de143494c0b295cca9337e1e96b00e0"); 66 | DaVinci.with(this).getHttpRequest().doGet("http://api.openweathermap.org/data/2.5/weather", map, this); 67 | 68 | DaVinci.with(this).getHttpRequest().doGet("http://api.openweathermap.org/data/2.5/weather", map, this); 69 | 70 | DaVinci.with(this).getHttpRequest().doGet("http://api.openweathermap.org/data/2.5/weather", map, this); 71 | 72 | image3.setOnClickListener(new View.OnClickListener() { 73 | @Override 74 | public void onClick(View v) { 75 | startActivity(new Intent(MainActivity.this, ListActivity.class)); 76 | } 77 | }); 78 | 79 | String path = "/sdcard/Download/cc_logo.png"; 80 | JSONObject jsonObject = new JSONObject(); 81 | try { 82 | JSONObject header = new JSONObject(); 83 | header.put("tokenId", "0e5495fb-da46-4b28-95ea-e9f6aec1d69a"); 84 | jsonObject.put("_header_", header); 85 | } catch (JSONException e) { 86 | e.printStackTrace(); 87 | } 88 | 89 | DaVinci.with(this).getUploader().extra("args", jsonObject).upload("http://192.168.3.117:12821/ecp/openapi/qs/file/upload", path, new OnVinciUploadListener() { 90 | @Override 91 | public void onVinciUploadSuccess(JSONObject response) { 92 | 93 | } 94 | 95 | @Override 96 | public void onVinciUploadFailed(String reason) { 97 | 98 | } 99 | }); 100 | 101 | DaVinci.with().addThreadPool("one", 1); 102 | DaVinci.with().tag("one").getImageLoader().load("http://y3.ifengimg.com/fashion_spider/dci_2012/02/20a78c36cc31225b1a7efa89f566f591.jpg").resize(600).into(image3); 103 | 104 | OutputStream out; 105 | try { 106 | out = new FileOutputStream(Environment.getExternalStorageDirectory() + "/download/" + "a.txt"); 107 | } catch (FileNotFoundException e) { 108 | e.printStackTrace(); 109 | return; 110 | } 111 | final TextView tv = (TextView)findViewById(R.id.test_text); 112 | DaVinci.with().getDownloader().body(jsonObject.toString()).download("http://ec2-52-192-96-229.ap-northeast-1.compute.amazonaws.com:12821/ecp/openapi/qs/file/download/p/2016/07/06/03/f5d28e3065244ab9952858f991838246.txt" 113 | , out, new OnVinciDownloadListener() { 114 | @Override 115 | public void onVinciDownloadSuccess() { 116 | 117 | } 118 | 119 | @Override 120 | public void onVinciDownloadFailed(String reason) { 121 | 122 | } 123 | 124 | @Override 125 | public void onVinciDownloadProgress(int progress) { 126 | VinciLog.e("progress = " + progress); 127 | 128 | tv.setText(String.valueOf(progress)); 129 | } 130 | }); 131 | } 132 | 133 | @Override 134 | public void onDaVinciRequestSuccess(String jsonObject) { 135 | Log.i("DaVinciTest", toString()); 136 | } 137 | 138 | @Override 139 | public void onDaVinciRequestFailed(int code, String reason) { 140 | 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 15 | 16 |