Android開發中使用Glide V4 中Generated API特性
Android Glide4 非同步圖片框架
實戰專案案例
- Kotlin Android Extensions+Android MVP專案(RxJava+Rerotfit+OkHttp+Glide)
- Anko Layout+MVP(Glide,Retrofit,OkHttp,RxJava)開發Android運用程式
Google在2013年釋出了網路文字和圖片非同步載入的Volley框架,而在2014年的Google IO app中推舉Glide框架來載入圖片。這說明,Glide比起Volley中ImageRequst更具備優勢,節省記憶體和節省寬頻資料。
這裡,Volley框架和Glide框架用載入同樣的網路資源,進行比較了一番。
RecyclerView中使用Volley的NetWorkImageView的記憶體情況:
RecyclerView中ImageView使用Glide的記憶體情況:
若是不熟悉Glide框架使用情況,可以閱讀Glide 框架和Glide v4新特性。
使用Glide v4中的Generated API 開發
前期配置,在專案中Gradle中引入庫的依賴:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
//Glide框架引入
compile 'com.github.bumptech.glide:glide:4.0.0-RC0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC0'
}
自定義AppGlideModule:
為運用程式定義一個帶有@GlideModule
註解的AppGlideModule,運用程式會使用和AppGlideMoudle同一個包下的GlideApp類。通過GlideApp.with()
方式使用Glide的Generated API。
@GlideModule
public final class CustomAppGlideModule extends AppGlideModule{
/**
* 通過GlideBuilder設定預設的結構(Engine,BitmapPool ,ArrayPool,MemoryCache等等).
* @param context
* @param builder
*/
@Override
public void applyOptions(Context context, GlideBuilder builder) {
//重新設定記憶體限制
builder.setMemoryCache(new LruResourceCache(10*1024*1024));
}
/**
* 為App註冊一個自定義的String型別的BaseGlideUrlLoader
*
* @param context
* @param registry
*/
@Override
public void registerComponents(Context context, Registry registry) {
registry.append(String.class, InputStream.class,new CustomBaseGlideUrlLoader.Factory());
}
/**
* 清單解析的開啟
*
* 這裡不開啟,避免新增相同的modules兩次
* @return
*/
@Override
public boolean isManifestParsingEnabled() {
return false;
}
}
注意點:
- 必需帶有
@GlideModule
註解。 isManifestParsingEnabled()
返回false,關閉解析AndroidManifest,不需要再配置GlideModule.
自定義BaseGlideUrlLoader:
根據帶有圖片尺寸的URl,來獲取合適比例的圖片資源。通過指定String型別的Model, BaseGliUrlLOader中getgetURL()
來覆蓋原本的帶有http或者htpps的URL. 這裡處理方式來源於,Google IO App.
public class CustomBaseGlideUrlLoader extends BaseGlideUrlLoader<String> {
private static final ModelCache<String, GlideUrl> urlCache =
new ModelCache<>(150);
/**
* Url的匹配規則
*/
private static final Pattern PATTERN = Pattern.compile("__w-((?:-?\\d+)+)__");
public CustomBaseGlideUrlLoader(ModelLoader<GlideUrl, InputStream> concreteLoader,ModelCache<String, GlideUrl> modelCache) {
super(concreteLoader,modelCache);
}
/**
* If the URL contains a special variable width indicator (eg "__w-200-400-800__")
* we get the buckets from the URL (200, 400 and 800 in the example) and replace
* the URL with the best bucket for the requested width (the bucket immediately
* larger than the requested width).
*
* 控制載入的圖片的大小
*/
@Override
protected String getUrl(String model, int width, int height, Options options) {
Matcher m = PATTERN.matcher(model);
int bestBucket = 0;
if (m.find()) {
String[] found = m.group(1).split("-");
for (String bucketStr : found) {
bestBucket = Integer.parseInt(bucketStr);
if (bestBucket >= width) {
// the best bucket is the first immediately bigger than the requested width
break;
}
}
if (bestBucket > 0) {
model = m.replaceFirst("w"+bestBucket);
}
}
return model;
}
@Override
public boolean handles(String s) {
return true;
}
/**
* 工廠來構建CustormBaseGlideUrlLoader物件
*/
public static class Factory implements ModelLoaderFactory<String,InputStream>{
@Override
public ModelLoader<String, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new CustomBaseGlideUrlLoader(multiFactory.build(GlideUrl.class,InputStream.class),urlCache);
}
@Override
public void teardown() {
}
}
}
ProGuard Rules中新增混淆規則:
根據上面的自定義,保持AppGlideModule子類和GlideModule實現類不被混淆。
#Glide的混淆規則
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
使用許可權 : 聯網許可權,讀寫許可權,AndroidManifest.xml中自行配置。
確保GlideApp類正常引用:
當配置完以上步驟後,發覺不能使用GlideApp類。
解決方式:在AndroidStudio中Build–>Make Project
–>將會出現build/generated/source中,便可以使用GlideApp
使用GlideApp類用於各種場景:
1. 單個ImageView載入影象資源:
Url:https://www.baidu.com/img/bd_logo1.png
Uri:content://media/external/images/1
Resource Id :R.drawable.image或者R.mipmap.ic_launcher
當然,還有其他的影象資源。
載入本地圖片:
/**
* 載入本地圖片,這裡是mipmap資料夾下的資源
*/
private void loadLocalImage() {
RequestBuilder<Drawable> drawableRequestBuilder = GlideApp.with(this).load(R.mipmap.ic_launcher);
drawableRequestBuilder.into(this.local_iv);
}
載入網路圖片:
/**
* 從遠端網路上載入圖片
*/
private void loadRemoteImage() {
GlideApp.with(this).asBitmap()
.load(ImageResouce.imageResource[0])
.error(R.mipmap.ic_launcher)//佔點陣圖片
.placeholder(R.mipmap.ic_launcher)//異常圖片
.into(this.remote_iv);
}
預先下載,本地快取中載入:
/**
* 預先載入資源
*/
private void startPreload() {
GlideApp.with(this).asBitmap()
.load(ImageResouce.imageResource[1])
.diskCacheStrategy(DiskCacheStrategy.ALL)
.preload();
}
/**
* 預先下載原始圖片資源後,本地載入
*/
private void loadPreloadImage() {
GlideApp.with(this).asBitmap().load(ImageResouce.imageResource[1]).diskCacheStrategy(DiskCacheStrategy.ALL).into(this.preload_iv);
}
error 和placeholder的處理:
.error(R.mipmap.ic_launcher) //異常圖片
.placeholder(R.mipmap.ic_launcher) //佔點陣圖片
.fallback(R.mipmap.ic_launcher); //當url為空時,回撥顯示的圖片
2. RecyclerView(或者ListView,GridView)中載入圖片資源:
Glide單一要求是任何重複使用的View Target,呼叫Clear()API明確清除先前的載入,以防載入到舊資料。
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
ImageView imageView=holder.getImageView();
String url=imageList.get(position);
if(TextUtils.isEmpty(url)){
//清空舊資料的引用
GlideApp.with(context).clear(imageView);
//當資源為空時候,設定預設圖片
imageView.setImageResource(R.mipmap.ic_launcher);
}else{//開啟一個圖片載入
loadImage(url,imageView);
}
}
/**
* 載入圖片
* @param url
* @param imageView
*/
public void loadImage(String url,ImageView imageView){
RequestBuilder<Bitmap> bitmapRequestBuilder= GlideApp.with(context)
.asBitmap()//指定Bitmap型別的RequestBuilder
.load(url)//網路URL
.error(R.mipmap.ic_launcher)//異常圖片
.placeholder(R.mipmap.ic_launcher)//佔點陣圖片
.fallback(R.mipmap.ic_launcher);//當url為空時,顯示圖片
bitmapRequestBuilder.into(imageView);
}
3. 自定義Circle Transformation 實現圓角圖片:
Glide擁有兩個預設的轉換(transformation):
- Fit center:類似Android’s ScaleType.FIT_CENTER
- Center crop:類似Android’s ScaleType.CENTER_CROP
這裡繼承BitmapTransformation,複寫transform()
:
public class CircleTransform extends BitmapTransformation{
public CircleTransform(Context context){
super(context);
}
/**
* 重寫 生成圓角圖片
* @param pool
* @param toTransform
* @param outWidth
* @param outHeight
* @return
*/
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool,toTransform);
}
private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
//畫布中背景圖片與繪製圖片交集部分
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result;
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
}
}
Glide使用自定義的Transform,最後將圓形Bitmap載入到ImageView上:
/**
* 載入圖片
* @param url
* @param imageView
*/
public void loadImage(String url,ImageView imageView){
RequestBuilder<Bitmap> bitmapRequestBuilder= GlideApp.with(context)
.asBitmap()//指定Bitmap型別的RequestBuilder
.load(url)//網路URL
.error(R.mipmap.ic_launcher)//異常圖片
.placeholder(R.mipmap.ic_launcher)//佔點陣圖片
.fallback(R.mipmap.ic_launcher);//當url為空時,顯示圖片
RequestOptions requestOptions=new RequestOptions();
//在RequestOptions中使用Transformations
requestOptions.transform(new CircleTransform(context));
//RequestBuilder<Bitmap> 中新增RequestOptions
bitmapRequestBuilder.apply(requestOptions).into(imageView);
}
4. 自定義BitmapImageViewTarget實現圓角圖片:
自定義一個BitmapImageViewTarget,複寫setResource()
:
public class CircularBitmapImageViewTarget extends BitmapImageViewTarget {
private Context context;
private ImageView imageView;
public CircularBitmapImageViewTarget(Context context,ImageView view) {
super(view);
this.context=context;
this.imageView=view;
}
/**
* 重寫 setResource(),生成圓角的圖片
* @param resource
*/
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable bitmapDrawable= RoundedBitmapDrawableFactory.create(this.context.getResources(),resource);
/**
* 設定圖片的shape為圓形.
*
* 若是需要制定圓角的度數,則呼叫setCornerRadius()。
*/
bitmapDrawable.setCircular(true);
this.imageView.setImageDrawable(bitmapDrawable);
}
}
Glide使用自定義ViewTarget:
/**
* 載入圖片
* @param url
* @param imageView
*/
public void loadImage(String url,ImageView imageView){
RequestBuilder<Bitmap> bitmapRequestBuilder= GlideApp.with(context)
.asBitmap()//指定Bitmap型別的RequestBuilder
.load(url)//網路URL
.error(R.mipmap.ic_launcher)//異常圖片
.placeholder(R.mipmap.ic_launcher)//佔點陣圖片
.fallback(R.mipmap.ic_launcher);//當url為空時,顯示圖片
//在RequestBuilder<Bitmap> 中使用自定義的ImageViewTarget
bitmapRequestBuilder.into(new CircularBitmapImageViewTarget(context,imageView));
}
專案執行效果如下:
專案程式碼連結:https://github.com/13767004362/GlideDemo
資源彙總:
Glide 框架: http://blog.csdn.net/hexingen/article/details/72577453
Glide 3.x到4.x的變化:http://blog.csdn.net/hexingen/article/details/72578066
問題彙總:
在listView或者RecyclerView中使用Glide框架,記憶體劇增或者爆記憶體溢位(OutOfMemoryError):
原因:在ImageView中scaleType使用了fitxy屬性:
<ImageView android:id="@+id/item_movielist_iv" android:layout_width="100dp" android:layout_height="100dp" android:scaleType="fitXY"/>
將fitXY改動成:fitCenter 或者centerCrop,記憶體情況如下:
解決同一URL遠端圖片,多次按不同大小比例載入多次載入的問題:
Preload Images,將URL對應的資料來源即原圖儲存下載,下次按比例來本地載入:
diskCacheStrategy(DiskCacheStrategy.ALL)
相關文章
- Glide V4 框架新特性(Migrating from v3 to v4)IDE框架
- Android應用開發中如何使用隱藏的APIAndroidAPI
- Android開發中API層的最佳實踐AndroidAPI
- Android:Glide使用AndroidIDE
- Android中如何使用Lambda表示式高效開發Android
- Android開發--RecyclerView使用,看AndroidL新特性,android5.0新特性AndroidView
- Android示例應用:開源框架Glide的使用Android框架IDE
- Android開發教程-使用DataBinding(六)RecyclerViewAdapter中的使用AndroidViewAPT
- 在 Laravel 中 Jwt 的使用 與 基礎 API 開發的搭建LaravelJWTAPI
- API開發中如何使用限速應對大規模訪問API
- Glide中的快取IDE快取
- Android Studio中NDK開發Android
- Android開發教程 - 使用Data Binding(四)在Fragment中的使用AndroidFragment
- Android開發教程 - 使用Data Binding(三)在Activity中的使用Android
- [譯] 如何在 Android 開發中充分利用多攝像頭 APIAndroidAPI
- Android 開發:glide圓角,圓形,效率問題AndroidIDE
- Android應用開發-圖片載入庫GlideAndroidIDE
- Android 開發中的SSL pinningAndroid
- 聊聊Android開發中的MVP模式AndroidMVP模式
- Android開發中巧用Activity和FragmentAndroidFragment
- 【Mysql】MySQL 5.7新特性之Generated Column(函式索引)MySql函式索引
- Android API 開發包介紹AndroidAPI
- 細數Android開源專案中那些頻繁使用的併發庫中的類Android
- Android開發中利用ObjectAnimator實現ArcMenuAndroidObject
- 瞭解 Android API 中的 SharedPreferencesAndroidAPI
- Android API開發之OpenGL開發之Android OpenGL STL詳解AndroidAPI
- 在安卓系統上使用Google Analytics API V4安卓GoAPI
- Android中的使用Android
- Git 實際開發中的使用Git
- oracle開發中序列的使用(轉)Oracle
- glide使用IDE
- 【Glide】使用IDE
- Android開發中的Kotlin Coroutine VS RxJavaAndroidKotlinRxJava
- Android開發中陰影效果的實現Android
- android開發過程中遇到的問題Android
- Android開發中的MVP架構詳解AndroidMVP架構
- Android開發中如何結束所有的activityAndroid
- 前沿探索|AI 在 API 開發測試中的應用AIAPI