├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── FrescoDwonImage.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── zdz │ │ └── com │ │ └── frescodwonimage │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── zdz │ │ │ └── com │ │ │ └── frescodwonimage │ │ │ ├── FrescoApplication.java │ │ │ ├── FrescoUtil.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.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 │ └── zdz │ └── com │ └── frescodwonimage │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | FrescoDwonImage -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /FrescoDwonImage.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FrescoDownImage 2 | 3 | http://blog.csdn.net/zhaodai11?viewmode=contents 4 | 5 | Fresco是Facebook发布的开源的图片加载框架,堪称目前最好用的图片加载库,使用简单。 6 | 中文文档地址 http://fresco-cn.org/docs/index.html。 7 | github地址:https://github.com/facebook/fresco。 8 | 9 | 因为要做图片下载功能,但是网上使用Fresco做图片下载的资料很少,特在此做一个总结一下。 10 | 11 | Fresco使用的是三级缓存。1. Bitmap缓存 2. 未解码图片的内存缓存 3. 文件缓存。 12 | 按照正常逻辑 在图片显示出来后,才能下载。所以图片已经被请求过一次,这里没有必要在发网络请求重新去下载图片。可以直接去取缓存中图片。 13 | 14 | 具体思路: 15 | 1.判断图片是否被缓存到磁盘,如果已经缓存,直接拷贝一份,到图片下载目录。 16 | 2.如果没有缓存到磁盘,就去获取缓存中的bitmap,然后直接保存到本地。 17 | 18 | Fresco 本地缓存路径可以通过setMainDiskCacheConfig()配置。默认的缓存路径 "/Android/data/" + PackageName + "/cache/imagepipeline_cache"目录下,最大缓存空间为300MB. 19 | 20 | Fresco可以根据图片url获取到磁盘缓存CacheKey,方法: 21 | 22 | ``` 23 | CacheKey cacheKey =DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(Uri.parse(picUrl))); 24 | ``` 25 | 26 | 通过CacheKey查找磁盘中有没有缓存文件:如果配置了 27 | 28 | ``` 29 | public static File getCachedImageOnDisk(CacheKey cacheKey) { 30 | File localFile = null; 31 | if (cacheKey != null) { 32 | if (ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey)) { 33 | BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); 34 | localFile = ((FileBinaryResource) resource).getFile(); 35 | } else if (ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().hasKey(cacheKey)) { 36 | BinaryResource resource = ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().getResource(cacheKey); 37 | localFile = ((FileBinaryResource) resource).getFile(); 38 | } 39 | } 40 | return localFile; 41 | } 42 | ``` 43 | 44 | 如果返回的localFile不为空的话,将文件拷贝到相应下载目录,重命名就可以了。 45 | 46 | 如果返回的localFile为空的话,去获取缓存中的bitmap,并保存到下载目录即可。 47 | ``` 48 | ImageRequest imageRequest = ImageRequestBuilder 49 | .newBuilderWithSource(Uri.parse(picUrl)) 50 | .setProgressiveRenderingEnabled(true) 51 | .build(); 52 | 53 | ImagePipeline imagePipeline = Fresco.getImagePipeline(); 54 | DataSource> 55 | dataSource = imagePipeline.fetchDecodedImage(imageRequest, context); 56 | 57 | dataSource.subscribe(new BaseBitmapDataSubscriber() { 58 | @Override 59 | public void onNewResultImpl(Bitmap bitmap) { 60 | if (bitmap == null) { 61 | Toast.makeText(context, "保存图片失败啦,无法下载图片", Toast.LENGTH_SHORT).show(); 62 | } 63 | File appDir = new File(Environment.getExternalStorageDirectory(), "Coderfun"); 64 | if (!appDir.exists()) { 65 | appDir.mkdir(); 66 | } 67 | String fileName = desc + ".jpg"; 68 | File file = new File(appDir, fileName); 69 | try { 70 | FileOutputStream fos = new FileOutputStream(file); 71 | assert bitmap != null; 72 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 73 | fos.flush(); 74 | fos.close(); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | 80 | @Override 81 | public void onFailureImpl(DataSource dataSource) { 82 | } 83 | }, CallerThreadExecutor.getInstance()); 84 | ``` 85 | 86 | 相关代码上传到github : 87 | https://github.com/zhaodaizheng/FrescoDownImage 88 | 89 | 有问题欢迎大家指教,感谢~ 90 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "zdz.com.frescodwonimage" 9 | minSdkVersion 15 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 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.3.0' 26 | compile 'com.facebook.fresco:fresco:0.10.0' 27 | } 28 | -------------------------------------------------------------------------------- /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 /Users/zhaodaizheng/Desktop/develop/adt-bundle-mac-x86_64-20140702/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/zdz/com/frescodwonimage/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package zdz.com.frescodwonimage; 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 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/zdz/com/frescodwonimage/FrescoApplication.java: -------------------------------------------------------------------------------- 1 | package zdz.com.frescodwonimage; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.drawee.backends.pipeline.Fresco; 6 | 7 | /** 8 | * Created by zhaodaizheng on 15/10/13. 9 | */ 10 | public class FrescoApplication extends Application { 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | Fresco.initialize(this); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/zdz/com/frescodwonimage/FrescoUtil.java: -------------------------------------------------------------------------------- 1 | package zdz.com.frescodwonimage; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.net.Uri; 6 | import android.os.Environment; 7 | import android.util.Log; 8 | 9 | import com.facebook.binaryresource.BinaryResource; 10 | import com.facebook.binaryresource.FileBinaryResource; 11 | import com.facebook.cache.common.CacheKey; 12 | import com.facebook.common.executors.CallerThreadExecutor; 13 | import com.facebook.common.references.CloseableReference; 14 | import com.facebook.datasource.DataSource; 15 | import com.facebook.drawee.backends.pipeline.Fresco; 16 | import com.facebook.imagepipeline.cache.DefaultCacheKeyFactory; 17 | import com.facebook.imagepipeline.core.ImagePipeline; 18 | import com.facebook.imagepipeline.core.ImagePipelineFactory; 19 | import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber; 20 | import com.facebook.imagepipeline.image.CloseableImage; 21 | import com.facebook.imagepipeline.request.ImageRequest; 22 | import com.facebook.imagepipeline.request.ImageRequestBuilder; 23 | 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | import java.io.FileOutputStream; 27 | import java.io.IOException; 28 | import java.nio.channels.FileChannel; 29 | 30 | /** 31 | * Created by zhaodaizheng on 16/5/20. 32 | */ 33 | public class FrescoUtil { 34 | 35 | private static final String TAG = "FrescoUtil"; 36 | public static final String IMAGE_PIC_CACHE_DIR = Environment.getExternalStorageDirectory().getPath()+"/Android/"; 37 | /** 38 | * 保存图片 39 | * 40 | * @param activity 41 | * @param picUrl 42 | */ 43 | public static void savePicture(String picUrl,Context context) { 44 | 45 | File picDir = new File(IMAGE_PIC_CACHE_DIR); 46 | 47 | if (!picDir.exists()) { 48 | picDir.mkdir(); 49 | } 50 | CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(Uri.parse(picUrl))); 51 | File cacheFile = getCachedImageOnDisk(cacheKey); 52 | if (cacheFile == null) { 53 | downLoadImage(Uri.parse(picUrl),"down",context); 54 | return; 55 | } else { 56 | copyTo(cacheFile,picDir,"down"); 57 | } 58 | } 59 | 60 | public static File getCachedImageOnDisk(CacheKey cacheKey) { 61 | File localFile = null; 62 | if (cacheKey != null) { 63 | if (ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey)) { 64 | BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); 65 | localFile = ((FileBinaryResource) resource).getFile(); 66 | } else if (ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().hasKey(cacheKey)) { 67 | BinaryResource resource = ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().getResource(cacheKey); 68 | localFile = ((FileBinaryResource) resource).getFile(); 69 | } 70 | } 71 | return localFile; 72 | } 73 | 74 | 75 | /** 76 | * 复制文件 77 | * 78 | * @param src 源文件 79 | * @param dst 目标文件 80 | * @return 81 | */ 82 | public static boolean copyTo(File src, File dir, String filename) { 83 | 84 | FileInputStream fi = null; 85 | FileOutputStream fo = null; 86 | FileChannel in = null; 87 | FileChannel out = null; 88 | try { 89 | fi = new FileInputStream(src); 90 | in = fi.getChannel();//得到对应的文件通道 91 | File dst; 92 | dst = new File(dir, filename + ".jpg"); 93 | fo = new FileOutputStream(dst); 94 | out = fo.getChannel();//得到对应的文件通道 95 | in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道 96 | return true; 97 | } catch (IOException e) { 98 | return false; 99 | } finally { 100 | try { 101 | 102 | if (fi != null) { 103 | fi.close(); 104 | } 105 | 106 | if (in != null) { 107 | in.close(); 108 | } 109 | 110 | if (fo != null) { 111 | fo.close(); 112 | } 113 | 114 | if (out != null) { 115 | out.close(); 116 | } 117 | 118 | } catch (IOException e) { 119 | e.printStackTrace(); 120 | return false; 121 | } 122 | } 123 | 124 | } 125 | 126 | 127 | public static void downLoadImage(Uri uri, final String filename, Context context) { 128 | ImageRequest imageRequest = ImageRequestBuilder 129 | .newBuilderWithSource(uri) 130 | .setProgressiveRenderingEnabled(true) 131 | .build(); 132 | ImagePipeline imagePipeline = Fresco.getImagePipeline(); 133 | DataSource> 134 | dataSource = imagePipeline.fetchDecodedImage(imageRequest, context); 135 | dataSource.subscribe(new BaseBitmapDataSubscriber() { 136 | @Override 137 | public void onNewResultImpl(Bitmap bitmap) { 138 | if (bitmap == null) { 139 | Log.e(TAG,"保存图片失败啦,无法下载图片"); 140 | } 141 | File appDir = new File(IMAGE_PIC_CACHE_DIR); 142 | if (!appDir.exists()) { 143 | appDir.mkdir(); 144 | } 145 | String fileName = filename + ".jpg"; 146 | File file = new File(appDir, fileName); 147 | try { 148 | FileOutputStream fos = new FileOutputStream(file); 149 | assert bitmap != null; 150 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 151 | fos.flush(); 152 | fos.close(); 153 | } catch (IOException e) { 154 | e.printStackTrace(); 155 | } 156 | } 157 | 158 | @Override 159 | public void onFailureImpl(DataSource dataSource) { 160 | } 161 | }, CallerThreadExecutor.getInstance()); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/zdz/com/frescodwonimage/MainActivity.java: -------------------------------------------------------------------------------- 1 | package zdz.com.frescodwonimage; 2 | 3 | import android.net.Uri; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.Toast; 9 | 10 | import com.facebook.drawee.view.SimpleDraweeView; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | 14 | private SimpleDraweeView draweeView; 15 | private Button btn_down; 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | btn_down = (Button) findViewById(R.id.btn_down); 21 | Uri uri = Uri.parse("http://pic.meizitu.com/wp-content/uploads/2012a/01/24/06.jpg"); 22 | draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view); 23 | draweeView.setImageURI(uri); 24 | 25 | btn_down.setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | FrescoUtil.savePicture("http://pic.meizitu.com/wp-content/uploads/2012a/01/24/06.jpg",MainActivity.this); 29 | Toast.makeText(MainActivity.this,"下载成功!路径:"+FrescoUtil.IMAGE_PIC_CACHE_DIR+"down.jpg",Toast.LENGTH_SHORT).show(); 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 |