1. Что такое Glide?
Glide — это популярная библиотека Android с открытым исходным кодом для загрузки изображений, видео и анимированных GIF-файлов. С Glide вы можете загружать и отображать мультимедиа из разных источников, таких как удаленные серверы или локальная файловая система.
По умолчанию Glide использует пользовательскую реализацию HttpURLConnection для загрузки изображений через Интернет. Тем не менее, Glide также предоставляет плагины для других популярных сетевых библиотек, таких как Volley или OkHttp .
2. Так зачем использовать Glide?
Разработка собственных функций загрузки и отображения мультимедиа в Java может быть реальной проблемой: вам нужно позаботиться о кэшировании, декодировании, управлении сетевыми подключениями, потоке, обработке исключений и многом другом. Glide — это простая в использовании, хорошо спланированная, хорошо документированная и тщательно протестированная библиотека, которая может сэкономить вам много драгоценного времени и избавить вас от головной боли.
В этом уроке мы узнаем о Glide 3, создав простое приложение для создания галереи изображений. Он загружает изображения через Интернет и отображает их в виде миниатюр в RecyclerView , а когда пользователь нажимает на любое изображение, он открывает детальное действие, содержащее большее изображение.
3. Создайте проект Android Studio
MainActivity
свою Android Studio и создайте новый проект с пустым действием под названием MainActivity
.
4. Объявить зависимости
После создания нового проекта укажите следующие зависимости в вашем build.gradle
.
01
02
03
04
05
06
07
08
09
10
11
|
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:
01
02
03
04
05
06
07
08
09
10
|
<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 ).
залп
1
2
3
4
5
6
|
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
01
02
03
04
05
06
07
08
09
10
|
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. Добавить интернет-разрешение
Поскольку Glide собирается выполнить сетевой запрос на загрузку изображений через Интернет, нам нужно включить разрешение INTERNET
в наш AndroidManifest.xml .
1
|
<uses-permission android:name=»android.permission.INTERNET» />
|
6. Создайте макет
Мы начнем с создания нашего RecyclerView
.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?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, который будет использоваться для каждого элемента ( ImageView
) в RecyclerView
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<?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
для RecyclerView
данными. Прежде чем мы сделаем это, давайте создадим нашу простую модель данных.
7. Создайте модель данных
Мы собираемся определить простую модель данных для нашего RecyclerView
. Эта модель реализует Parcelable для высокопроизводительной передачи данных из одного компонента в другой. В нашем случае данные будут перенесены из SpaceGalleryActivity
в SpacePhotoActivity
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
|
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 данными. Мы также реализуем прослушиватель SpacePhotoActivity
чтобы открыть детальное действие — SpacePhotoActivity
передав ему экземпляр SpacePhoto
в качестве дополнительного. Детальное действие покажет крупный план изображения. Мы создадим его в следующем разделе.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
|
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 выполнял свою работу — извлекать изображения из Интернета и отображать их в отдельных ImageView
, используя наш метод RecyclerView onBindViewHolder()
когда пользователь прокручивает приложение.
01
02
03
04
05
06
07
08
09
10
11
12
|
// …
@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)
: локальный идентификатор ресурса приложения, предпочтительно для рисования, который будет заполнителем до тех пор, пока изображение не будет загружено и отображено. -
into(ImageView imageView)
: представление целевого изображения, в которое будет помещено изображение.
Помните, что Glide также может загружать локальные изображения. Просто передайте идентификатор ресурса Android, путь к файлу или URI в качестве аргумента методу load()
.
Изменение размера изображения и преобразование
Вы можете изменить размер изображения до его отображения в ImageView
с помощью .override(int width, int height)
Glide .override(int width, int height)
. Это полезно для создания миниатюр в вашем приложении при загрузке другого размера изображения с сервера. Обратите внимание, что размеры указаны в пикселях, а не в dp.
Доступны также следующие преобразования изображений:
-
fitCenter()
: s равномерно запечатывает изображение (с сохранением соотношения сторон изображения), чтобы изображение помещалось в заданную область. Все изображение будет видимым, но может быть вертикальное или горизонтальное заполнение. -
centerCrop()
: равномерно масштабирует изображение (поддерживая соотношение сторон изображения), так что изображение заполняет заданную область, с максимально возможным отображением изображения. При необходимости изображение будет обрезано по горизонтали или вертикали для соответствия.
10. Инициализация адаптера
Здесь мы создаем наш RecyclerView
с GridLayoutManager
в качестве менеджера макета, инициализируем наш адаптер и привязываем его к RecyclerView
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
// …
@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 получал Bitmap
. В противном случае загрузка завершится неудачно, и будет вызван обратный вызов .error()
результате чего будет отображен извлекаемый ресурс, возвращенный из обратного вызова ошибки.
Вы также можете использовать asGif()
если хотите, чтобы загруженное изображение было в формате GIF. (Вскоре я объясню, как GIF-файлы работают в Glide.)
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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
, который покажет версию загруженного изображения в полном разрешении.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?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 будет кэшировать его в памяти и на диске, сохраняя повторные сетевые запросы и позволяя быстрее получать изображение. Итак, Glide сначала проверит, доступно ли изображение в памяти или на диске, прежде чем загружать его из сети.
Однако в зависимости от вашего приложения вы можете избежать кэширования, например, если отображаемые изображения могут часто меняться и не будут перезагружаться.
Так как же отключить кеширование?
Вы можете избежать кэширования памяти, вызвав .skipMemoryCache(true)
. Но имейте в виду, что образ по-прежнему будет кэшироваться на диске — чтобы предотвратить это, вы также используете метод .diskCacheStrategy(DiskCacheStrategy strategy)
, который принимает одно из следующих значений перечисления:
-
DiskCacheStrategy.NONE
: данные не сохраняются в кэш. -
DiskCacheStrategy.SOURCE
: исходные данные, сохраненные в кеше. -
DiskCacheStrategy.RESULT
: сохраняет результаты данных после преобразований в кэш. -
DiskCacheStrategy.ALL
: кэширует как исходные, так и преобразованные данные.
Чтобы полностью избежать кеширования памяти и диска, просто вызовите оба метода один за другим:
1
2
3
4
5
6
|
Glide.with(this)
.load(spacePhoto.getUrl())
.asBitmap()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
|
13. Запрос слушателей
В Glide вы можете реализовать RequestListener
для мониторинга состояния запроса, который вы сделали при загрузке изображения. Только один из этих методов будет вызван.
-
onException()
: срабатывает всякий раз, когда возникает исключение, поэтому вы можете обрабатывать исключения в этом методе. -
onResourceReady()
: срабатывает при успешной загрузке изображения.
Возвращаясь к нашему приложению галереи изображений, давайте немного изменим отображение, используя объект RequestListener
, который установит растровое изображение в ImageView
а также изменим цвет фона макета, извлекая темный и вибрирующий цвет нашего изображения с помощью палитры Android. API .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// …
@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
:
1
2
3
4
|
dependencies {
// …
compile ‘com.android.support:palette-v7:25.1.1’
}
|
14. Тестирование приложения
Наконец, вы можете запустить приложение! Нажмите на миниатюру, чтобы получить полноразмерную версию изображения.
15. Анимации
Если вы запустите приложение, вы заметите перекрестную анимацию, которая появляется во время отображения изображения. В Glide это включено по умолчанию, но вы можете отключить его, вызвав dontAnimate()
, что приведет к отображению изображения без анимации.
Вы также можете настроить анимацию кроссфейда, вызывая crossFade(int duration)
, передавая длительность в миллисекундах, чтобы ускорить или замедлить ее — по умолчанию 300 миллисекунд.
Анимированные картинки
Очень просто отобразить анимированный GIF в вашем приложении с помощью Glide. Это работает так же, как отображение обычного изображения.
1
2
3
4
5
6
7
8
|
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, в противном случае загрузка не удастся, и вместо этого будет показано Drawable
переданное методу .error()
.
Воспроизведение видео
К сожалению, Glide не поддерживает загрузку и отображение видео через URL. Вместо этого он может только загружать и отображать видео, уже сохраненные на телефоне. Показать видео, передав его URI методу load()
.
1
2
3
|
Glide.with(context)
.load(Uri.fromFile(new File(«your/video/file/path»))
.into(imageView)
|
Вывод
Прекрасная работа! В этом учебном пособии вы создали полное приложение для создания галереи изображений с помощью Glide, а также узнали, как работает библиотека и как ее интегрировать в свой собственный проект. Вы также узнали, как отображать как локальные, так и удаленные изображения, как отображать анимированные GIF-файлы и видео, и как применять преобразования изображений, такие как изменение размера. Не только это, но вы уже видели, как легко включить кэширование, обработку ошибок и прослушивание пользовательских запросов.
Чтобы узнать больше о Glide, вы можете обратиться к его официальной документации . Чтобы узнать больше о кодировании для Android, ознакомьтесь с другими нашими курсами и учебными пособиями здесь, на Envato Tuts +!