Fresco强大的图片加载框架

     图片加载时项目中不可缺少的一个功能,很多程序员都会使用一些框架来帮助处理要加载的图像,往往在处理图片加载时很有可能会出现OOM的错误,这样会很蛋疼。现在主流的都是使用ImageLoader、Volley、Picasso,或者是一些自己封装的工具类。最近我发现一个新的图片加载框架Fresco是faceBook中使用的强大框架,代码简洁功能强大,可以很好的解决OOM的现象。

    具体的配置我就略过,直接进入使用环节,如果想了解的话这是Fresco的官网(中文的)https://www.fresco-cn.org/docs/index.html 

    加载图片代码很简单,首先要在继承Application类里初始化

Fresco强大的图片加载框架_第1张图片

   在MainActivity类里直接可以加载URLset到ImageView上,这里注意Fresco不接受相对路径,只能传绝对路径。


   到这里我们代码功能就实现了,接下来是xml文件的设置

Fresco强大的图片加载框架_第2张图片

   Fresco使用的是自定义的ImageView,里面的fresco标签要加上红框内的才可以(这里有个坑就是fresco的自定义属性不能提示,只能自己查官网复制,可能有的人能提示具体我还不太清楚为什么)

Fresco强大的图片加载框架_第3张图片

    接下来是一些常用的自定义属性的具体意义和使用注意

    android:id="@+id/my_image_view"
    android:layout_width="20dp"   // 不支持wrap_content 如果要设置宽高比, 需要在Java代码中指定setAspectRatio(1.33f);
    android:layout_height="20dp"    // 不支持wrap_content 
    fresco:fadeDuration="300"
    fresco:actualImageScaleType="focusCrop" // 设置图片缩放. 通常使用focusCrop,该属性值会通过算法把人头像放在中间
    fresco:placeholderImage="@color/wait_color" // 下载成功之前显示的图片
    fresco:placeholderImageScaleType="fitCenter" 
    fresco:failureImage="@drawable/error"// 加载失败的时候显示的图片
    fresco:failureImageScaleType="centerInside"
    fresco:retryImage="@drawable/retrying"// 加载失败,提示用户点击重新加载的图片(会覆盖failureImage的图片)
    fresco:retryImageScaleType="centerCrop"
    fresco:progressBarImage="@drawable/progress_bar"// 提示用户正在加载,和加载进度无关
    fresco:progressBarImageScaleType="centerInside"
    fresco:progressBarAutoRotateInterval="1000"
    fresco:backgroundImage="@color/blue"
    fresco:overlayImage="@drawable/watermark"
    fresco:pressedStateOverlayImage="@color/red"
    fresco:roundAsCircle="false"// 是不是设置圆圈
    fresco:roundedCornerRadius="1dp"// 圆角角度,180的时候会变成圆形图片
    fresco:roundTopLeft="true"
    fresco:roundTopRight="false"
    fresco:roundBottomLeft="false"
    fresco:roundBottomRight="true"
    fresco:roundWithOverlayColor="@color/corner_color"
    fresco:roundingBorderWidth="2dp"
    fresco:roundingBorderColor="@color/border_color"
  />
到这里就完成了是不是很简单,可能有人会疑惑,既然是图片加载框架,图片保存到本地哪里呢?我也是找了很久才知道,Fresco并没有将图片下载到本地,而是缓存到本地注意是缓存到本地,我们只能找到缓存本地的文件复制到本地目录下或者下载到本地。下面我找了一个工具类就可以解决这个问题了。

public class FrescoUtil {

    private static final String TAG = "FrescoUtil";
    public static final String IMAGE_PIC_CACHE_DIR = Environment.getExternalStorageDirectory().getPath()+"/AndroidIamge/";
    /**
     * 保存图片
     *
     * @param activity
     * @param picUrl
     */
    public static void savePicture(String picUrl,Context context) {

        File picDir = new File(IMAGE_PIC_CACHE_DIR);

        if (!picDir.exists()) {
            picDir.mkdir();
        }
        CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(Uri.parse(picUrl)),context);
        File cacheFile = getCachedImageOnDisk(cacheKey);
        if (cacheFile == null) {
            downLoadImage(Uri.parse(picUrl),"down",context);
            return;
        } else {
            copyTo(cacheFile,picDir,"down");
        }
    }

    public static File getCachedImageOnDisk(CacheKey cacheKey) {
        File localFile = null;
        if (cacheKey != null) {
            if (ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey)) {
                BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey);
                localFile = ((FileBinaryResource) resource).getFile();
            } else if (ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().hasKey(cacheKey)) {
                BinaryResource resource = ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache().getResource(cacheKey);
                localFile = ((FileBinaryResource) resource).getFile();
            }
        }
        return localFile;
    }


    /**
     * 复制文件
     *
     * @param src 源文件
     * @param dst 目标文件
     * @return
     */
    public static boolean copyTo(File src, File dir, String filename) {

        FileInputStream fi = null;
        FileOutputStream fo = null;
        FileChannel in = null;
        FileChannel out = null;
        try {
            fi = new FileInputStream(src);
            in = fi.getChannel();//得到对应的文件通道
            File dst;
            dst = new File(dir, filename + ".jpg");
            fo = new FileOutputStream(dst);
            out = fo.getChannel();//得到对应的文件通道
            in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
            return true;
        } catch (IOException e) {
            return false;
        } finally {
            try {

                if (fi != null) {
                    fi.close();
                }

                if (in != null) {
                    in.close();
                }

                if (fo != null) {
                    fo.close();
                }

                if (out != null) {
                    out.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

    }


    public static void downLoadImage(Uri uri, final String filename, Context context) {
        ImageRequest imageRequest = ImageRequestBuilder
                .newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(true)
                .build();
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource>
                dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
        dataSource.subscribe(new BaseBitmapDataSubscriber() {
            @Override
            public void onNewResultImpl(Bitmap bitmap) {
                if (bitmap == null) {
                    Log.e(TAG,"保存图片失败啦,无法下载图片");
                }
                File appDir = new File(IMAGE_PIC_CACHE_DIR);
                if (!appDir.exists()) {
                    appDir.mkdir();
                }
                String fileName = filename + ".jpg";
                File file = new File(appDir, fileName);
                try {
                    FileOutputStream fos = new FileOutputStream(file);
                    assert bitmap != null;
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
            }
        }, CallerThreadExecutor.getInstance());
    }
}
然后我们在加载时候改造一下


这样图片就会加载到本地了,具体路径和文件名字可以自行去更改


你可能感兴趣的:(Fresco强大的图片加载框架)