Glide的各种处理方式

Glide 一个专注于平滑滚动的图片加载和缓存库

在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路。现在市面上知名的图片加载库有UIL,Picasso,Volley ImageLoader,Fresco以及我们今天的主角Glide。它们各有千秋,不能评定谁一定比谁好,只能说哪一个更适合你。

我的理解

下面我来谈一下个人对这些图片加载库的理解,如有错误,还望指教。

Universal Image Loader:一个强大的图片加载库,包含各种各样的配置,最老牌,使用也最广泛。

Picasso: Square出品,必属精品。和OkHttp搭配起来更配呦!

Volley ImageLoader:Google官方出品,可惜不能加载本地图片~

Fresco:Facebook出的,天生骄傲!不是一般的强大。

Glide:Google推荐的图片加载库,专注于流畅的滚动。

更多详情请看stackoverflow上这个问题

初试Glide

下面进入今天的主题,相信之前很多同学都看到过这篇介绍Glide的文章,中文版在这里。文中从各个方面介绍和比较了Glide与Picasso,总体来说二者极为相似,有着近乎相同的API的使用风格。但Glide在缓存策略和加载GIF方面略胜一筹。最后作者也极力推荐了这个库。

而且据说在Google新出的Photos应用中,到处可见Glide的踪迹。看到这里,你是不是已经迫不及待的想试一试这个库呢?就在你下定决心尝试一记的时候,你又听说Yelp app(据说是美国的大众点评)也在使用这个吊炸天的库。你的心中激动万分,发四一定要使用这个库。说干就干,打开Android Studio,在builde.gradle里面添加上

compile 'com.github.bumptech.glide:glide:3.6.1'
复制代码

然后全局搜索图片加载的地方,全部换成了下面的代码:

Glide.with(mContext)
        .load(url)
        .placeholder(R.drawable.loading_spinner)
        .crossFade()
        .into(myImageView);
复制代码

在经过漫长的编译过程之后,再次打开APP,看到有着渐现效果的图片呈现在你的面前,你不禁叫道:“wocao,真TM帅!为什么我以前没有发现呢?”。

不过在你使用了几天之后你会发现一些问题:

为什么 有的图片第一次加载的时候只显示占位图,第二次才显示正常的图片呢?

为什么 我总会得到类似You cannot start a load for a destroyed activity这样的异常呢?

为什么 我不能给加载的图片setTag()呢?

为什么?为什么?这么NB的库竟然会有这么多的问题。没错,这就是我今天要讲的重点。怎么避免上面的问题发生。

一些解决方案

1.如果你刚好使用了这个圆形Imageview库或者其他的一些自定义的圆形Imageview,而你又刚好设置了占位的话,那么,你就会遇到第一个问题。如何解决呢? 方案一: 不设置占位; 方案二:使用Glide的Transformation API自定义圆形Bitmap的转换。这里是一个已有的例子; 方案三:使用下面的代码加载图片:

Glide.with(mContext)
    .load(url) 
    .placeholder(R.drawable.loading_spinner)
    .into(new SimpleTarget<Bitmap>(width, height) {
        @Override 
        public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
            // setImageBitmap(bitmap) on CircleImageView 
        } 
    }); 
复制代码

感谢aeecc0d15a40指出该方法在listview上复用有问题的bug,如果在listview中加载CircleImageView,请不要使用该方法。 方案四:不使用Glide的默认动画:

Glide.with(mContext)
    .load(url) 
    .dontAnimate()
    .placeholder(R.drawable.loading_spinner)
    .into(circleImageview); 
复制代码

2.至于第二个问题,请记住一句话:不要再非主线程里面使用Glide加载图片,如果真的使用了,请把context参数换成getApplicationContext。更多的细节请参考这个issue

3.为什么不能设置Tag,是因为你使用的姿势不对哦。如何为ImageView设置Tag呢?且听我细细道来。 方案一:使用setTag(int,object)方法设置tag,具体用法如下: Java代码是酱紫的:

Glide.with(context).load(urls.get(i).getUrl()).fitCenter().into(imageViewHolder.image);
        imageViewHolder.image.setTag(R.id.image_tag, i);
        imageViewHolder.image.setOnClickListener(new View.OnClickListener() {
            @Override
                int position = (int) v.getTag(R.id.image_tag);
                Toast.makeText(context, urls.get(position).getWho(), Toast.LENGTH_SHORT).show();
            }
        });
复制代码

同时在values文件夹下新建ids.xml,添加

<item name="image_tag" type="id"/>
复制代码

大功告成!

方案二:从Glide的3.6.0之后,新添加了全局设置的方法。具体方法如下: 先实现GlideMoudle接口,全局设置ViewTaget的tagId:

public class MyGlideMoudle implements GlideModule{
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        ViewTarget.setTagId(R.id.glide_tag_id);
    }

    @Override
    public void registerComponents(Context context, Glide glide) {

    }
}
复制代码

同样,也需要在ids.xml下添加id

<item name="glide_tag_id" type="id"/>
复制代码

最后在AndroidManifest.xml文件里面添加

<meta-data
    android:name="com.yourpackagename.MyGlideMoudle"
    android:value="GlideModule" />
复制代码

又可以愉快的玩耍了,嘻嘻`(∩_∩)′。

方案三:写一个继承自ImageViewTaget的类,复写它的get/setRequest方法。

Glide.with(context).load(urls.get(i).getUrl()).fitCenter().into(new ImageViewTarget<GlideDrawable>(imageViewHolder.image) {
            @Override
            protected void setResource(GlideDrawable resource) {
                imageViewHolder.image.setImageDrawable(resource);
            }

            @Override
            public void setRequest(Request request) {
                imageViewHolder.image.setTag(i);
                imageViewHolder.image.setTag(R.id.glide_tag_id,request);
            }

            @Override
            public Request getRequest() {
                return (Request) imageViewHolder.image.getTag(R.id.glide_tag_id);
            }
        });

        imageViewHolder.image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = (int) v.getTag();
                Toast.makeText(context, urls.get(position).getWho(), Toast.LENGTH_SHORT).show();
            }
        });
复制代码

一些使用技巧

1.Glide.with(context).resumeRequests()和 Glide.with(context).pauseRequests()

当列表在滑动的时候,调用pauseRequests()取消请求,滑动停止时,调用resumeRequests()恢复请求。这样是不是会好些呢?

2.Glide.clear()

当你想清除掉所有的图片加载请求时,这个方法可以帮助到你。

3.ListPreloader

如果你想让列表预加载的话,不妨试一下ListPreloader这个类。

一些基于Glide的优秀库

1.glide-transformations

一个基于Glide的transformation库,拥有裁剪,着色,模糊,滤镜等多种转换效果,赞的不行不行的~~

2.GlidePalette

一个可以在Glide加载时很方便使用Palette的库。

 

基于Glide V4.0封装的GlideImageView,可监听加载图片时的进度

96

 

GlideImageView 是基于Glide V4.0设计的,实现如下特性:

1、通过提供的属性可以设置图片的圆角、边框。
2、可以设置点击触摸图片时的颜色、透明度。
3、一行代码加载来自网络、res、SDCard中的图片,可加载成圆形。
4、可以监听加载图片时的进度。

下面这张图是设置了图片的圆角、边框并设置了触摸图片时的颜色

GitHub地址

APK下载地址,去手机上体验吧 (‿)

具体使用说明如下

Gradle:

compile 'com.sunfusheng:glideimageview:1.0.0'

Maven:

<dependency>
  <groupId>com.sunfusheng</groupId>
  <artifactId>glideimageview</artifactId>
  <version>1.0.0</version>
  <type>pom</type>
</dependency>

ShapeImageView 和 GlideImageView 共同的属性

该库提供了一个ShapeImageView类,可以在xml当中,也可以在代码中设置图片的一些属性,
当然这些属性也可以在GlideImageView上面设置,具体属性如下

Attribute 属性Description 描述
siv_border_color边框颜色
siv_border_width边框宽度
siv_pressed_color触摸图片时的颜色
siv_pressed_alpha触摸图片时的颜色透明度: 0.0f - 1.0f
siv_radius圆角弧度
siv_shape_type两种形状类型:默认是0:rectangle、1:circle

下面是在xml中和代码中设置的效果

xml中设置代码中设置

一行代码加载来自网络、res、SDCard中图片

public GlideImageView loadImage(String url, int placeholderResId);
public GlideImageView loadLocalImage(@DrawableRes int resId, int placeholderResId); 
public GlideImageView loadLocalImage(String localPath, int placeholderResId);

一行代码加载来自网络、res、SDCard中图片成圆形

public GlideImageView loadCircleImage(String url, int placeholderResId); 
public GlideImageView loadLocalCircleImage(int resId, int placeholderResId);
public GlideImageView loadLocalCircleImage(String localPath, int placeholderResId);

如果你觉得上面的方法还不能满足你,那么你可以通过下面的方法追加自己想要的属性来加载图片

RequestOptions requestOptions(int placeholderResId);
RequestOptions circleRequestOptions(int placeholderResId);

GlideImageView load(int resId, RequestOptions options);
GlideImageView load(Uri uri, RequestOptions options);
GlideImageView load(String url, RequestOptions options);

如果你还是觉得得不到满足,好吧,我提供了GlideImageLoader类加载图片,比如这样加载图片:先加载缩略图再加载高清图片,并监听加载的进度

private void loadImage(String image_url_thumbnail, String image_url) {
    RequestOptions requestOptions = glideImageView.requestOptions(R.color.black)
            .centerCrop()
            .skipMemoryCache(true) // 跳过内存缓存
            .diskCacheStrategy(DiskCacheStrategy.NONE); // 不缓存到SDCard中

    glideImageView.getImageLoader().setOnGlideImageViewListener(image_url, new OnGlideImageViewListener() {
        @Override
        public void onProgress(int percent, boolean isDone, GlideException exception) {
            progressView.setProgress(percent);
            progressView.setVisibility(isDone ? View.GONE : View.VISIBLE);
        }
    });

    glideImageView.getImageLoader().requestBuilder(image_url, requestOptions)
            .thumbnail(Glide.with(ImageActivity.this) // 加载缩略图
                    .load(image_url_thumbnail)
                    .apply(requestOptions))
            .transition(DrawableTransitionOptions.withCrossFade()) // 动画渐变加载
            .into(glideImageView);
}

该库提供两种监听加载图片进度的Listener,总有一款是你想要的

public interface OnGlideImageViewListener {
    void onProgress(int percent, boolean isDone, GlideException exception);
}

public interface OnProgressListener {
    void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception);
}

GitHub地址

GLide加载图片还能这样干——基于Glide4.0完美封装

一个基于GLide加载图片的封装开源框架。可以监听加载图片时的进度 ,可以设置图片的圆角、边框。可加载成圆形。

来自孙福生一个开源框架。项目地址为:github.com/sfsheng0322…

该库是基于Glide V4.0设计的,实现如下特性:

  • 1、通过提供的属性可以设置图片的圆角、边框。
  • 2、可以设置点击触摸图片时的颜色、透明度。
  • 3、一行代码加载来自网络、res、SDCard中的图片,可加载成圆形。
  • 4、可以监听加载图片时的进度。

话不多说,上我们的我们的效果图:

 

项目预览

项目预览

 

加载不同形式的图片:

public void loadLocalImage(@DrawableRes int resId, int placeholderResId) {
            load(resId, requestOptions(placeholderResId));
        }

        public void loadLocalImage(String localPath, int placeholderResId) {
            load(FILE + localPath, requestOptions(placeholderResId));
        }

        public void loadCircleImage(String url, int placeholderResId) {
            load(url, circleRequestOptions(placeholderResId));
        }

        public void loadLocalCircleImage(int resId, int placeholderResId) {
            load(resId, circleRequestOptions(placeholderResId));
        }

        public void loadLocalCircleImage(String localPath, int placeholderResId) {
            load(FILE + localPath, circleRequestOptions(placeholderResId));
        }复制代码

效果图:

 

加载不同风格的图片

加载不同风格的图片

 

一些关键的类:

  • GlideView 对ImageView进一步的封装

  • GlideImageLoader 对Glide.load的进一步封装

  • CircleProgressView和ShapeImageView 封装加载图片的进度条

CircleProgressView和ShapeImageView是自定义ImageView,其中封装了一些自定义属性
可以在可以在代码中设置图片的一些属性, 当然这些属性也可以在GlideImageView上面设置。

eg:

// 设置边框颜色
public void setBorderColor(@ColorRes int id) {
    this.borderColor = getResources().getColor(id);
    invalidate();
}

// 设置边框宽度
public void setBorderWidth(int borderWidth) {
    this.borderWidth = DisplayUtil.dip2px(getContext(), borderWidth);
    invalidate();
}

// 设置图片按下颜色透明度
public void setPressedAlpha(float pressAlpha) {
    this.pressedAlpha = pressAlpha;
}

// 设置图片按下的颜色
public void setPressedColor(@ColorRes int id) {
    this.pressedColor = getResources().getColor(id);
    pressedPaint.setColor(pressedColor);
    pressedPaint.setAlpha(0);
    invalidate();
}复制代码

具体属性如下

Attribute 属性Description 描述
siv_border_color边框颜色
siv_border_width边框宽度
siv_pressed_color触摸图片时的颜色
siv_pressed_alpha触摸图片时的颜色透明度: 0.0f - 1.0f
siv_radius圆角弧度
siv_shape_type两种形状类型:默认是0:rectangle、1:circle

代码:

 image41.load(cat_thumbnail, requestOptions).listener(new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                if (exception != null && !TextUtils.isEmpty(exception.getMessage())) {
                    Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                }
                progressView1.setProgress(percent);
                progressView1.setVisibility(isDone ? View.GONE : View.VISIBLE);
            }
        });复制代码

加载gif:

 

加载gif小图片

加载gif小图片

 

GLide的缓存策略:

内存缓存

让我们想象一个非常简单的请求,从网络中加载图片到 ImageView。

Glide  
    .with( context )
    .load( eatFoodyImages[0] )
    .skipMemoryCache( true )
    .into( imageViewInternet );复制代码

调用了 .skipMemoryCache(true) 去明确告诉 Glide 跳过内存缓存。这意味着 Glide 将不会把这张图片放到内存缓存中去。这里需要明白的是,这只是会影响内存缓存!Glide 将会仍然利用磁盘缓存来避免重复的网络请求

跳过磁盘缓存

图片在这段代码片段中将不会被保存在磁盘缓存中。然而,默认的它将仍然使用内存缓存!为了把这里两者都禁用掉,两个方法一起调用:

Glide  
    .with( context )
    .load( eatFoodyImages[0] )
    .diskCacheStrategy( DiskCacheStrategy.NONE )
    .skipMemoryCache( true )
    .into( imageViewInternet );复制代码

自定义磁盘缓存行为

Picasso 仅仅缓存了全尺寸的图像。然而 Glide 缓存了原始图像,全分辨率图像和另外小版本的图像。比如,如果你请求的一个图像是 1000x1000 像素的,但你的 ImageView 是 500x500 像素的,Glide 将会把这两个尺寸都进行缓存。

现在你将会理解对于 .diskCacheStrategy() 方法来说不同的枚举参数的意义:

  • DiskCacheStrategy.NONE 什么都不缓存,就像刚讨论的那样

  • DiskCacheStrategy.SOURCE 仅仅只缓存原来的全分辨率的图像。在我们上面的例子中,将会只有一个 1000x1000 像素的图片

  • DiskCacheStrategy.RESULT 仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
  • DiskCacheStrategy.ALL 缓存所有版本的图像(默认行为)

用 DiskCacheStrategy.SOURCE 去告诉 Glide 仅仅保存原始图片:

Glide  
    .with( context )
    .load( eatFoodyImages[2] )
    .diskCacheStrategy( DiskCacheStrategy.SOURCE )
    .into( imageViewFile );        复制代码

在项目中提供了GlideImageLoader类加载图片,比如这样加载图片:先加载缩略图再加载高清图片,并监听加载的进度

private void loadImage(String image_url_thumbnail, String image_url) {
    RequestOptions requestOptions = glideImageView.requestOptions(R.color.black)
            .centerCrop()
            .skipMemoryCache(true) // 跳过内存缓存
            .diskCacheStrategy(DiskCacheStrategy.NONE); // 不缓存到SDCard中

    glideImageView.getImageLoader().setOnGlideImageViewListener(image_url, new OnGlideImageViewListener() {
        @Override
        public void onProgress(int percent, boolean isDone, GlideException exception) {
            progressView.setProgress(percent);
            progressView.setVisibility(isDone ? View.GONE : View.VISIBLE);
        }
    });

    glideImageView.getImageLoader().requestBuilder(image_url, requestOptions)
            .thumbnail(Glide.with(ImageActivity.this) // 加载缩略图
                    .load(image_url_thumbnail)
                    .apply(requestOptions))
            .transition(DrawableTransitionOptions.withCrossFade()) // 动画渐变加载
            .into(glideImageView);
}复制代码

加载进度时效果如下:

 

加载时进度条监听

加载时进度条监听

 

项目Github链接地址

github.com/androidstar…

下载慢?CSDN下载链接:

download.csdn.net/detail/andr…

Glide 加载图片保存至本地指定路径

/**
         * Glide 加载图片保存到本地
         *
         * imgUrl 图片地址
         * imgName 图片名称
         */
        Glide.with(context).load(imgUrl).asBitmap().toBytes().into(new SimpleTarget<byte[]>() {
            @Override
            public void onResourceReady(byte[] bytes, GlideAnimation<? super byte[]> glideAnimation) {
                try {
                    savaBitmap(imgName, bytes);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

// 保存图片到手机指定目录
    public void savaBitmap(String imgName, byte[] bytes) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String filePath = null;
            FileOutputStream fos = null;
            try {
                filePath = Environment.getExternalStorageDirectory().getCanonicalPath() + "/MyImg";
                File imgDir = new File(filePath);
                if (!imgDir.exists()) {
                    imgDir.mkdirs();
                }
                imgName = filePath + "/" + imgName;
                fos = new FileOutputStream(imgName);
                fos.write(bytes);
                Toast.makeText(context, "图片已保存到" + filePath, Toast.LENGTH_SHORT).show();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fos != null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            Toast.makeText(context, "请检查SD卡是否可用", Toast.LENGTH_SHORT).show();
        }
    }

Glide 加载图片回调方法

Glide.with(context).load(imgUrl)
                .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model,
                                               Target<GlideDrawable> target,
                                               boolean isFirstResource) {
                        // 可替换成进度条
                        Toast.makeText(context, "图片加载失败", Toast.LENGTH_SHORT).show();
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model,
                                                   Target<GlideDrawable> target,
                                                   boolean isFromMemoryCache,
                                                   boolean isFirstResource) {
                        // 图片加载完成,取消进度条
                        Toast.makeText(context, "图片加载成功", Toast.LENGTH_SHORT).show();
                        return false;
                    }
                }).error(R.mipmap.ic_launcher_round)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);

 

          Observable.create(new ObservableOnSubscribe<File>() {
            @Override
            public void subscribe(ObservableEmitter<File> e) throws Exception {
                //通过gilde下载得到file文件,这里需要注意android.permission.INTERNET权限
                e.onNext(Glide.with(mContext)
                        .load(imagePathList.get(currentViewPosition).getPath())
                        .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
                        .get());
                e.onComplete();
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(new Consumer<File>() {
            @Override
            public void accept(File file) throws Exception {
                //获取到下载得到的图片,进行本地保存
                File pictureFolder = Environment.getExternalStorageDirectory();
                //第二个参数为你想要保存的目录名称
                File appDir = new File(pictureFolder, "your_picture_save_path");
                if (!appDir.exists()) {
                    appDir.mkdirs();
                }
                String fileName = System.currentTimeMillis() + ".jpg";
                File destFile = new File(appDir, fileName);
                //把gilde下载得到图片复制到定义好的目录中去
                copy(file, destFile);
     
                // 最后通知图库更新
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                        Uri.fromFile(new File(destFile.getPath()))));
            }
        });

带上复制文件的方法:

     /**
         * 复制文件
         *
         * @param source 输入文件
         * @param target 输出文件
         */
        public void copy(File source, File target) {
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;
            try {
                fileInputStream = new FileInputStream(source);
                fileOutputStream = new FileOutputStream(target);
                byte[] buffer = new byte[1024];
                while (fileInputStream.read(buffer) > 0) {
                    fileOutputStream.write(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fileInputStream.close();
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    最后需要注意的下载保存需要读写权限,6.0以后需手动申请权限
    android.permission.WRITE_EXTERNAL_STORAGE
    android.permission.READ_EXTERNAL_STORAGE
---------------------
 

随笔 - 60  文章 - 0  评论 - 6

Glide实现查看图片和保存图片到手机

 两种方式, 推荐方式一

方式一 downloadOnly

创建一个 ImageActivity

复制代码

public class ImageActivity extends AppCompatActivity {

    private static final String TAG = "ImageActivity";

    private ImageView iv;

    Bitmap bitmap;

    private String mUrl;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image);

        iv = (ImageView) findViewById(R.id.iv);

        // 图片的url 从另一个Activity传过来
        String url = getIntent().getStringExtra(EXTRA_URL);
        mUrl = url;

        loadImage(url);

        // 长按 ImageView 把图片保存到手机

        iv.setOnLongClickListener(new View.OnLongClickListener(){
            @Override
            public boolean onLongClick(View v) {

                download(mUrl)
                return true;
            }
        });
    }
    
    // 加载并显示图片
    public void loadImage(String url) {
        Glide.with(this).load(url).placeholder(R.drawable.image_loading)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .listener(new RequestListener<String, GlideDrawable>() {
                @Override
                public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {

                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    Log.d(TAG, "onResourceReady: mode: " + model);

                    // 如果return true; 则 into(iv) 不起作用, 要手动设置图片
                    // iv.setImageDrawable(resource);

                    return false;
                }
            })
            .into(iv);
    }
    
    // 保存图片到手机
    public void download(final String url) {

        new AsyncTask<Void, Integer, File>() {

            @Override
            protected File doInBackground(Void... params) {
                File file = null;
                try {
                    FutureTarget<File>  future = Glide
                            .with(ImageActivity.this)
                            .load(url)
                            .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);

                    file = future.get();

                    // 首先保存图片
                    File pictureFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile();

                    File appDir = new File(pictureFolder ,"Beauty");
                    if (!appDir.exists()) {
                        appDir.mkdirs();
                    }
                    String fileName = System.currentTimeMillis() + ".jpg";
                    File destFile = new File(appDir, fileName);

                    FileUtil.copy(file, destFile);

                    // 最后通知图库更新
                    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                            Uri.fromFile(new File(destFile.getPath()))));


                } catch (Exception e) {
                    Log.e(TAG, e.getMessage());
                }
                return file;
            }

            @Override
            protected void onPostExecute(File file) {

                Toast.makeText(ImageActivity.this, "saved in Pictures/GankBeauty", Toast.LENGTH_SHORT).show();
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                super.onProgressUpdate(values);
            }
        }.execute();
    }
}

复制代码

 

 

以上代码 从另一个activity得到 图片的 url , 然后使用Glide 图片加载库 将图片显示到 ImageView上, 长按ImageView可以将图片保存到手机的 Pictures/Beauty 目录中

这是基本的代码模板, 实际情况更复杂,比如Android 6 还有运行时申请存储权限的问题。

 

方式二 asBitmap  bitmap.compress

还有一种保存图片的方式也有很多人用,但是经过我对比发现并不好,推荐上面的方式。另一种方式的代码如下

 

把上面 loadImage 换成 下面的 loadBitmap

复制代码

    public void loadBitmap(String url) {
        Glide.with(this).load(url).asBitmap().placeholder(R.drawable.image_loading)
                .listener(new RequestListener<String, Bitmap>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {

                        Log.i(TAG, "onResourceReady: thread is " + Thread.currentThread().getName());
                        isReady = true;
                        bitmap = resource;
                        iv.setImageBitmap(resource);
 

                        return false;
                    }
                })
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);

    }

复制代码

 

把上面的 download 换成下面的 saveImage

复制代码

public void saveImage() {

        // 首先保存图片
        File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile();

        File appDir = new File(file ,"Beauty");
        boolean createed = false;
        if (!appDir.exists()) {
            createed =  appDir.mkdirs();
        }
        String fileName = System.currentTimeMillis() + ".jpg";
        File currentFile = new File(appDir, fileName);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(currentFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        // 最后通知图库更新
        this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                Uri.fromFile(new File(currentFile.getPath()))));



    }

复制代码

这种方式把图片变成bitmap , 保存的时候又重新压缩bitmap 保存到手机。

 

总结

从电脑下载图片,然后与保存到手机的图片对比,发现bitmap的方式得到的图片体积变大。

而第一种方式下载的图片与从电脑上下载的图片体积一致,md5一致。

所以推荐downloadOnly方式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值