1.什么是滑翔?
Glide是一个流行的开源Android库,用于加载图像,视频和动画GIF。 使用Glide,您可以从许多不同的源(例如,远程服务器或本地文件系统)加载和显示媒体。
默认情况下,Glide使用HttpURLConnection的自定义实现来通过Internet加载图像。 但是,Glide还为其他流行的网络库(例如Volley或OkHttp)提供了插件。
2.那么为什么要使用Glide?
用Java开发自己的媒体加载和显示功能可能是一个真正的痛苦:您必须注意缓存,解码,管理网络连接,线程,异常处理等。 Glide是一个易于使用,经过精心计划,有据可查且经过全面测试的库,可以为您节省很多宝贵的时间,并且省去了一些麻烦。
在本教程中,我们将通过构建一个简单的图库应用程序来学习Glide 3。 它将通过互联网加载图像,并在RecyclerView中将其显示为缩略图,并且当用户单击任何图像时,它将打开包含较大图像的详细信息活动。
3.创建一个Android Studio项目
启动您的Android Studio并创建一个名为MainActivity
的空活动的新项目。
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