使用Glide编码图库Android应用

最终产品图片
您将要创造的

1.什么是滑翔?

Glide是一个流行的开源Android库,用于加载图像,视频和动画GIF。 使用Glide,您可以从许多不同的源(例如,远程服务器或本地文件系统)加载和显示媒体。

默认情况下,Glide使用HttpURLConnection的自定义实现来通过Internet加载图像。 但是,Glide还为其他流行的网络库(例如VolleyOkHttp)提供了插件。

2.那么为什么要使用Glide?

用Java开发自己的媒体加载和显示功能可能是一个真正的痛苦:您必须注意缓存,解码,管理网络连接,线程,异常处理等。 Glide是一个易于使用,经过精心计划,有据可查且经过全面测试的库,可以为您节省很多宝贵的时间,并且省去了一些麻烦。

在本教程中,我们将通过构建一个简单的图库应用程序来学习Glide 3。 它将通过互联网加载图像,并在RecyclerView中将其显示为缩略图,并且当用户单击任何图像时,它将打开包含较大图像的详细信息活动。

3.创建一个Android Studio项目

启动您的Android Studio并创建一个名为MainActivity的空活动的新项目。

Android Studio新项目截图

4.声明依赖

创建新项目后,在build.gradle指定以下依赖build.gradle

repositories {
  mavenCentral() // jcenter() works as well because it pulls from Maven Central
}

dependencies {
    // Glide
    compile 'com.github.bumptech.glide:glide:3.7.0'
    
    // Recyclerview
    compile 'com.android.support:recyclerview-v7:25.1.1'
}

或使用Maven:

<dependency>
  <groupId>com.github.bumptech.glide</groupId>
  <artifactId>glide</artifactId>
  <version>3.7.0</version>
</dependency>
<dependency>
  <groupId>com.google.android</groupId>
  <artifactId>support-v4</artifactId>
  <version>r7</version>
</dependency>

添加Glide依赖项后,确保同步项目。

集成库

如果要在项目中使用网络库(例如OkHttp或Volley)进行网络操作,建议为所使用的库包括特定的Glide集成(而不是捆绑HttpURLConnection的默认库)。

凌空抽射
dependencies {

    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.github.bumptech.glide:volley-integration:1.4.0@aar'
    compile 'com.mcxiaoke.volley:library:1.0.8'
}
OkHttp
dependencies {
      
    // okhttp 3
    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    
    // okhttp 2
    compile 'com.github.bumptech.glide:okhttp-integration:1.4.0@aar'
    compile 'com.squareup.okhttp:okhttp:2.2.0'
}

您可以访问官方的Glide集成库指南以获取更多信息。

5.添加Internet权限

由于Glide将执行网络请求以通过Internet加载图像,因此我们需要在我们的AndroidManifest.xml中包含INTERNET权限。

<uses-permission android:name="android.permission.INTERNET" />

6.创建布局

我们将从创建RecyclerView开始。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_images"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
</RelativeLayout>

创建自定义项目布局

接下来,让我们创建XML布局,该布局将用于RecyclerView每个项目( ImageView )。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
<ImageView
        android:id="@+id/iv_photo"
        android:adjustViewBounds="true"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"
        android:layout_width="match_parent"/>

</LinearLayout>

现在我们已经创建了布局,下一步是创建用于填充数据的RecyclerView适配器。 但是,在执行此操作之前,让我们创建简单的数据模型。

7.创建一个数据模型

我们将为RecyclerView定义一个简单的数据模型。 该模型实现了Parcelable,用于从一个组件到另一个组件的高性能数据传输。 在我们的例子中,数据将从SpaceGalleryActivity传输到SpacePhotoActivity

import android.os.Parcel;
import android.os.Parcelable;

public class SpacePhoto implements Parcelable {

    private String mUrl;
    private String mTitle;

    public SpacePhoto(String url, String title) {
        mUrl = url;
        mTitle = title;
    }

    protected SpacePhoto(Parcel in) {
        mUrl = in.readString();
        mTitle = in.readString();
    }

    public static final Creator<SpacePhoto> CREATOR = new Creator<SpacePhoto>() {
        @Override
        public SpacePhoto createFromParcel(Parcel in) {
            return new SpacePhoto(in);
        }

        @Override
        public SpacePhoto[] newArray(int size) {
            return new SpacePhoto[size];
        }
    };

    public String getUrl() {
        return mUrl;
    }

    public void setUrl(String url) {
        mUrl = url;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public static  SpacePhoto[] getSpacePhotos() {

        return new SpacePhoto[]{
                new SpacePhoto("http://i.imgur.com/zuG2bGQ.jpg", "Galaxy"),
                new SpacePhoto("http://i.imgur.com/ovr0NAF.jpg", "Space Shuttle"),
                new SpacePhoto("http://i.imgur.com/n6RfJX2.jpg", "Galaxy Orion"),
                new SpacePhoto("http://i.imgur.com/qpr5LR2.jpg", "Earth"),
                new SpacePhoto("http://i.imgur.com/pSHXfu5.jpg", "Astronaut"),
                new SpacePhoto("http://i.imgur.com/3wQcZeY.jpg", "Satellite"),
        };
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(mUrl);
        parcel.writeString(mTitle);
    }
}

8.创建适配器

我们将创建一个适配器,以使用数据填充RecyclerView。 我们还将实现一个单击侦听器,以打开详细信息活动SpacePhoto ,并额外SpacePhotoActivity传递一个SpacePhoto实例。 细节活动将显示图像的特写。 我们将在后面的部分中创建它。

public class MainActivity extends AppCompatActivity {
    // ... 
    private class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder>  {

        @Override
        public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            Context context = parent.getContext();
            LayoutInflater inflater = LayoutInflater.from(context);
            View photoView = inflater.inflate(R.layout.item_photo, parent, false);
            ImageGalleryAdapter.MyViewHolder viewHolder = new ImageGalleryAdapter.MyViewHolder(photoView);
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(ImageGalleryAdapter.MyViewHolder holder, int position) {

            SpacePhoto spacePhoto = mSpacePhotos[position];
            ImageView imageView = holder.mPhotoImageView;
        }

        @Override
        public int getItemCount() {
            return (mSpacePhotos.length);
        }

        public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

            public ImageView mPhotoImageView;

            public MyViewHolder(View itemView) {

                super(itemView);
                mPhotoImageView = (ImageView) itemView.findViewById(R.id.iv_photo);
                itemView.setOnClickListener(this);
            }

            @Override
            public void onClick(View view) {

                int position = getAdapterPosition();
                if(position != RecyclerView.NO_POSITION) {
                    SpacePhoto spacePhoto = mSpacePhotos[position];
                    Intent intent = new Intent(mContext, SpacePhotoActivity.class);
                    intent.putExtra(SpacePhotoActivity.EXTRA_SPACE_PHOTO, spacePhoto);
                    startActivity(intent);
                }
            }
        }

        private SpacePhoto[] mSpacePhotos;
        private Context mContext;

        public ImageGalleryAdapter(Context context, SpacePhoto[] spacePhotos) {
            mContext = context;
            mSpacePhotos = spacePhotos;
        }
    }
}

9.从URL加载图像

这是我们需要Glide进行工作的地方-在用户滚动应用程序时使用RecyclerView onBindViewHolder()方法从Internet上获取图像并将其显示在单个ImageView

// ...
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    Photo photo = mPhotoList.get(position);
    ImageView imageView = holder.mPhotoImageView;

     Glide.with(mContext)
            .load(spacePhoto.getUrl())
            .placeholder(R.drawable.ic_cloud_off_red)
            .into(imageView);
}
// ...

逐步介绍对Glide的调用:

  • with(Context context) :首先通过将上下文传递给with()方法来开始加载过程。
  • load(String string) :将图像源指定为目录路径,URI或URL。
  • placeholder(int resourceId) :本地应用程序资源ID,最好是可绘制的ID,在加载和显示图像之前将是一个占位符。
  • into(ImageView imageView) :将要放置图像的目标图像视图。

请注意,Glide还可以加载本地图像。 只需将Android资源ID,文件路径或URI作为参数传递给load()方法即可。

图像调整大小和变换

您可以使用Glide的.override(int width, int height)方法调整图像的大小,然后将其显示在ImageView 。 当从服务器加载不同大小的图像时,这对于在应用程序中创建缩略图很有用。 请注意,尺寸单位是像素,而不是dp。

还可以使用以下图像转换:

  • fitCenter() :s对图像进行统一缩放(保持图像的纵横比),以使图像适合给定区域。 整个图像将可见,但可能会有垂直或水平填充。
  • centerCrop() :均匀缩放图像(保持图像的宽高比),以使图像填充给定区域,并尽可能多地显示图像。 如果需要,图像将水平或垂直裁切以适合图像。

10.初始化适配器

在这里,我们使用GridLayoutManager作为布局管理器来创建RecyclerView ,初始化适配器,并将其绑定到RecyclerView

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

    RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this, 2);
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv_images);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(layoutManager);

    ImageGalleryAdapter adapter = new ImageGalleryAdapter(this, SpacePhoto.getSpacePhotos());
    recyclerView.setAdapter(adapter);

}
// ...

11.创建明细活动

创建一个新的活动并将其命名为SpacePhotoActivity 。 我们额外获得了SpacePhoto并像以前一样使用Glide加载图像。 在这里,我们期望文件或URL是Bitmap ,因此我们将使用asBitmap()使Glide接收asBitmap() Bitmap 。 否则,加载将失败,并且将触发.error()回调,从而导致显示从错误回调返回的可绘制资源。

如果要确保加载的图像是GIF,也可以使用asGif() 。 (我稍后将解释GIF如何在Glide中工作。)

import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;

public class SpacePhotoActivity extends AppCompatActivity {

    public static final String EXTRA_SPACE_PHOTO = "SpacePhotoActivity.SPACE_PHOTO";
    private ImageView mImageView;

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

        mImageView = (ImageView) findViewById(R.id.image);
        SpacePhoto spacePhoto = getIntent().getParcelableExtra(EXTRA_SPACE_PHOTO);
        
        Glide.with(this)
                .load(spacePhoto.getUrl())
                .asBitmap()
                .error(R.drawable.ic_cloud_off_red)
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .into(mImageView);
    }
}

请注意,我们还为加载的图像初始化了唯一的缓存: DiskCacheStrategy.SOURCE 。 我将在后面的部分中解释有关缓存的更多信息。

详细布局

这是显示详细信息活动的布局。 它只是显示一个可滚动的ImageView ,它将显示已加载图像的全分辨率版本。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <LinearLayout
                android:id="@+id/activity_character"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_gravity="center_vertical">

            <ImageView
                    android:id="@+id/image"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:adjustViewBounds="true"
                    android:scaleType="fitCenter"/>
            
        </LinearLayout>
    </ScrollView>
</LinearLayout>

12.滑行缓存

如果仔细观察,您会发现当您重新访问以前加载的图像时,它的加载速度甚至比以前更快。 是什么使它更快? Glide的缓存系统就是这样。

从互联网一次加载图像后,Glide会将其缓存在内存和磁盘中,从而节省了重复的网络请求并允许更快地检索图像。 因此,Glide将首先检查图像是否在内存或磁盘上可用,然后再从网络加载它。

但是,根据您的应用程序,您可能希望避免缓存-例如,如果显示的图像可能经常更改并且不被重新加载。

那么如何禁用缓存?

您可以通过调用.skipMemoryCache(true)来避免内存缓存。 但是请注意,映像仍将缓存在磁盘上—为防止这种情况,请使用.diskCacheStrategy(DiskCacheStrategy strategy)方法,该方法采用以下枚举值之一:

  • DiskCacheStrategy.NONE :没有数据保存到缓存。
  • DiskCacheStrategy.SOURCE :保存到缓存的原始数据。
  • DiskCacheStrategy.RESULT :将转换后的数据结果保存到缓存。
  • DiskCacheStrategy.ALL :缓存原始数据和转换后的数据。

要完全避免内存和磁盘缓存,只需一个接一个地调用这两个方法:

Glide.with(this)
        .load(spacePhoto.getUrl())
        .asBitmap()
        .skipMemoryCache(true)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .into(imageView);

13.请求监听器

在Glide中,您可以实现RequestListener来监视图像加载时发出的请求的状态。 这些方法中只有一种会被调用。

  • onException() :每当发生异常时触发,因此您可以在此方法中处理异常。
  • onResourceReady() :成功加载图像时触发。

回到我们的图片库应用程序,让我们使用RequestListener对象对显示进行一些修改,该对象将位图设置为ImageView并通过使用Android Palette提取图像的深色和振动色来更改布局的背景色API

// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...   
    Glide.with(this)
            .load(spacePhoto.getUrl())
            .asBitmap()
            .error(R.drawable.ic_cloud_off_red)
            .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) {
    
                    onPalette(Palette.from(resource).generate());
                    mImageView.setImageBitmap(resource);
    
                    return false;
                }
    
                public void onPalette(Palette palette) {
                    if (null != palette) {
                        ViewGroup parent = (ViewGroup) mImageView.getParent().getParent();
                        parent.setBackgroundColor(palette.getDarkVibrantColor(Color.GRAY));
                    }
                }
            })
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .into(mImageView);
}
// ...

如果您有一个进度对话框,在这里也可以隐藏它。 最后更改之后,请确保在build.gradle包括Palette依赖build.gradle

dependencies {
    // ...
    compile 'com.android.support:palette-v7:25.1.1'
}

14.测试应用

最后,您可以运行该应用程序! 单击缩略图以获取完整尺寸的图像。

运行应用程序屏幕快照的模拟器

15.动画

如果运行该应用程序,您会注意到在显示图像时会发生交叉淡入淡出的动画。 Glide默认情况下启用了此功能,但是您可以通过调用dontAnimate()来禁用它,这只会导致图像不显示任何动画。

您还可以通过调用crossFade(int duration)来自定义crossfade动画,传递持续时间(以毫秒为单位)以加快或降低它的速度-默认值为300毫秒。

GIF动画

使用Glide在您的应用程序中显示动画GIF非常简单。 它的作用与显示普通图像相同。

ImageView gifImageView = (ImageView) findViewById(R.id.iv_gif);

Glide.with(this)
        .load("http://i.imgur.com/Vth6CBz.gif")
        .asGif()
        .placeholder(R.drawable.ic_cloud_off_red)
        .error(R.drawable.ic_cloud_off_red)
        .into(gifImageView);

如果您期望图像是GIF,请调用asGif() -确保Glide接收到GIF,否则加载将失败,并且将显示传递给.error()方法的Drawable

播放影片

不幸的是,Glide不支持视频加载和通过URL显示。 相反,它只能加载和显示已经存储在手机上的视频。 通过将其URI传递给load()方法来显示视频。

Glide.with(context)
      .load(Uri.fromFile(new File("your/video/file/path"))
      .into(imageView)

结论

很好! 在本教程中,您已经使用Glide构建了一个完整的图像库应用程序,并且沿途学习了库的工作原理以及如何将其集成到自己的项目中。 您还学习了如何显示本地和远程图像,如何显示GIF动画和视频,以及如何应用图像转换(如调整大小)。 不仅如此,而且您已经看到启用缓存,错误处理和自定义请求侦听器是多么容易。

翻译自: https://code.tutsplus.com/tutorials/code-an-image-gallery-android-app-with-glide--cms-28207

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值