編輯:關於Android編程
一、特點
多線程的圖像加載
ImageLoader的配置(線程池的大小,HTTP選項,內存和光盤高速緩存,顯示圖像,以及其他)
緩存存儲器和/或設備的文件器系統(或SD卡)
可以“聽”加載過程中
可自定義每個顯示的圖像調用分隔的選項
Widget支持
Android 1.5以上支持
二、使用方法
1.設置緩存目錄(希望的緩存文件的目錄:imageloader/Cache)
File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "imageloader/Cache");
之後在ImageLoaderConfiguration的配置文件中通過設置
.discCache(new UnlimitedDiscCache(cacheDir))//自定義緩存路徑
2.配置ImageLoaderConfiguration(最好放在Application裡面)
ImageLoaderConfiguration config = new ImageLoaderConfiguration
.Builder(context)
.memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每個緩存文件的最大長寬
.discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)/設置緩存的詳細信息,最好不要設置這個
.threadPoolSize(3)//線程池內加載的數量
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通過自己的內存緩存實現
.memoryCacheSize(2 * 1024 * 1024)
.discCacheSize(50 * 1024 * 1024)
.discCacheFileNameGenerator(new Md5FileNameGenerator())//將保存的時候的URI名稱用MD5 加密
.tasksProcessingOrder(QueueProcessingType.LIFO)
.discCacheFileCount(100) //緩存的文件數量
.discCache(new UnlimitedDiscCache(cacheDir))//自定義緩存路徑
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超時時間
.writeDebugLogs() // Remove for release app
.build();//開始構建
最後調用ImageLoader.getInstance().init(config);//全局初始化此配置
3.得到實例化對象並設置參數
protected ImageLoader imageLoader = ImageLoader.getInstance();
DisplayImageOptions 的設置:
DisplayImageOptions options;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher) //設置圖片在下載期間顯示的圖片
.showImageForEmptyUri(R.drawable.ic_launcher)//設置圖片Uri為空或是錯誤的時候顯示的圖片
.showImageOnFail(R.drawable.ic_launcher) //設置圖片加載/解碼過程中錯誤時候顯示的圖片
.cacheInMemory(true)//設置下載的圖片是否緩存在內存中
.cacheOnDisc(true)//設置下載的圖片是否緩存在SD卡中
.considerExifParams(true) //是否考慮JPEG圖像EXIF參數(旋轉,翻轉)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//設置圖片以如何的編碼方式顯示
.bitmapConfig(Bitmap.Config.RGB_565)//設置圖片的解碼類型//
.decodingOptions(android.graphics.BitmapFactory.Options decodingOptions)//設置圖片的解碼配置
//.delayBeforeLoading(int delayInMillis)//int delayInMillis為你設置的下載前的延遲時間
//設置圖片加入緩存前,對bitmap進行設置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//設置圖片在下載前是否重置,復位
.displayer(new RoundedBitmapDisplayer(20))//是否設置為圓角,弧度為多少
.displayer(new FadeInBitmapDisplayer(100))//是否圖片加載好後漸入的動畫時間
.build();//構建完成
注:
以上配置中的:
1).imageScaleType(ImageScaleType imageScaleType) 是設置 圖片的縮放方式
縮放類型mageScaleType:
EXACTLY :圖像將完全按比例縮小的目標大小
EXACTLY_STRETCHED:圖片會縮放到目標大小完全
IN_SAMPLE_INT:圖像將被二次采樣的整數倍
IN_SAMPLE_POWER_OF_2:圖片將降低2倍,直到下一減少步驟,使圖像更小的目標大小
NONE:圖片不會調整
2).displayer(BitmapDisplayer displayer) 是設置 圖片的顯示方式
顯示方式displayer:
RoundedBitmapDisplayer(int roundPixels)設置圓角圖片
FakeBitmapDisplayer()這個類什麼都沒做
FadeInBitmapDisplayer(int durationMillis)設置圖片漸顯的時
SimpleBitmapDisplayer()正常顯示一張圖片
4.顯示調用方法
ImageLoader.getInstance().displayImage(imageUrl, imageView); // imageUrl代表圖片的URL地址,imageView代表承載圖片的IMAGEVIEW控件
ImageLoader.getInstance().displayImage(imageUrl, imageView,options); // imageUrl代表圖片的URL地址,imageView代表承載圖片的
5.監聽方法
①圖片加載時候帶加載情況的監聽
方法:
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,ImageLoadingListener listener) {}
ImageLoadingListener 用於監聽圖片的下載情況。
具體實現
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//開始加載的時候執行
}
@Override
public void onLoadingFailed(FailReason failReason) {
//加載失敗的時候執行
}
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加載成功的時候執行
}
@Override
public void onLoadingCancelled() {
//加載取消的時候執行
}});
②圖片加載時候,帶監聽又帶加載進度條的情況
調用:
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {}
具體實現:
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//開始加載的時候執行
}
@Override
public void onLoadingFailed(FailReason failReason) {
//加載失敗的時候執行
}
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加載成功的時候執行
}
@Override
public void onLoadingCancelled() {
//加載取消的時候執行
},new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current,int total) {
//在這裡更新 ProgressBar的進度信息
}
});
6.注意事項
注意事項
1.上述提到的2個權限必須加入,否則會出錯
2.ImageLoaderConfiguration必須配置並且全局化的初始化這個配置ImageLoader.getInstance().init(config); 否則也會出現錯誤提示
3.ImageLoader是根據ImageView的height,width確定圖片的寬高。
4.如果經常出現OOM
①減少配置之中線程池的大小,(.threadPoolSize).推薦1-5;
②使用.bitmapConfig(Bitmap.config.RGB_565)代替ARGB_8888;
③使用.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者 try.imageScaleType(ImageScaleType.EXACTLY);
④避免使用RoundedBitmapDisplayer.他會創建新的ARGB_8888格式的Bitmap對象;
⑤使用.memoryCache(new WeakMemoryCache()),不要使用.cacheInMemory();
String imageUri = "http://site.com/image.png"; // from Web
String imageUri = "file:///mnt/sdcard/image.png"; // from SD card
String imageUri = "content://media/external/audio/albumart/13"; // from content provider
String imageUri = "assets://image.png"; // from assets
String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)
Picasso(不再詳解一般用Glide)
Glide
一、集成
1.項目中集成Glide
在gradle中添加Glide庫:
dependencies {
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:appcompat-v7:23.1.1'
}
Glide的集成離不開v4包,所以必須添加support包。
2.Glide集成其他庫
Glide包含一些小的、可選的集成庫,目前Glide集成庫當中包含了訪問網絡操作的Volley和OkHttp:
(1)Volley集成
第一步、添加依賴
dependencies {
compile 'com.github.bumptech.glide:volley-integration:1.2.2'
compile 'com.mcxiaoke.volley:library:1.0.5'
}
第二步、創建Volley集成庫的GlideModule
然後改變混淆文件:
-keep class com.bumptech.glide.integration.volley.VolleyGlideModule
#or
-keep public class * implements com.bumptech.glide.module.GlideModule
(2)OkHttp集成
第一步、添加依賴
dependencies {
compile 'com.github.bumptech.glide:okhttp-integration:1.2.2'
compile 'com.squareup.okhttp:okhttp:2.0.0'
}
第二步、創建Volley集成庫的GlideModule
然後改變混淆文件:
-keep class com.bumptech.glide.integration.okhttp.OkHttpGlideModule
#or
-keep public class * implements com.bumptech.glide.module.GlideModule
(3)集成轉換器(此處只介紹集成庫,使用後面再講)
第一步、gradle添加依賴
repositories {
jcenter()
mavenCentral() // GPUImage for Android
}
dependencies {
compile 'jp.wasabeef:glide-transformations:2.0.1'
// If you want to use the GPU Filters
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.3.0'
}
通過這個轉換器庫,可以實現各式各樣的圖片,非常強大。
二、Glide配置
1.第一步:
public class GlideModelConfig implements GlideModule {
int diskSize = 1024 * 1024 * 100;
int memorySize = (int) (Runtime.getRuntime().maxMemory()) / 8; // 取1/8最大內存作為最大緩存
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// 定義緩存大小和位置
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskSize)); //內存中
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "cache", diskSize)); //sd卡中
// 默認內存和圖片池大小
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); // 默認內存大小
int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); // 默認圖片池大小
builder.setMemoryCache(new LruResourceCache(defaultMemoryCacheSize)); // 該兩句無需設置,是默認的
builder.setBitmapPool(new LruBitmapPool(defaultBitmapPoolSize));
// 自定義內存和圖片池大小
builder.setMemoryCache(new LruResourceCache(memorySize));
builder.setBitmapPool(new LruBitmapPool(memorySize));
// 定義圖片格式
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
builder.setDecodeFormat(DecodeFormat.PREFER_RGB_565); // 默認
}
@Override
public void registerComponents(Context context, Glide glide) {
}
}
2.第二步:
這GlideModel可以在AndroidManifest.xml文件中注冊,以便Glide能夠找到你的Module
3.第三步:
將上面的實現了加入到proguard.cfg當中,代碼混淆:
-keepnames class * com.example.jianglei.glidedemo.GlideModelConfig
可能遇到的問題:
Glide允許一個應用當中存在多個GlideModules,但是Glide並不會按照一個特殊的順序去調用已注冊的GlideModules,如果一個應用的多個依賴工程當中有多個相同的Modules,就有可能會產生沖突。
如果一個沖突是不可避免的,應用應該默認去定義一個自己的Module,用來手動地處理這個沖突,在進行Manifest合並的時候,可以用下面的標簽排除沖突的Module:
三、Glide使用詳情
1.基本使用:
Glide.with(context)
.load("xxxx.png")
.into(imageView);
Glide的with()可以接受的類型有如下:
Context context;
Activity activity;
FragmentActivity fragmentActivity;
Fragment fragment;
load()是加載目標資源,可以接受的參數類型有如下:
Uri uri;
String uriString;
File file;
Integer resourceId;
byte[] model;
String model;
into()就是加載資源完成後作什麼處理,它接受三種參數:
// 顯示在控件上
into(ImageView imageView);
// 通過回調獲得加載結果,可能在項目中,一個圖片在多個地方使用,可以在回調中獲得該圖片的Bitmap操作
into(Target target);
Glide.with(mContext).load(url).asBitmap().into(new SimpleTarget() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
image.setImageBitmap(resource);
}
});
Glide.with(mContext).load(url).asBitmap().into(new Target() {
@Override
public void onLoadStarted(Drawable placeholder) {
// 設置加載過程中的Drawable
}
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
// 設置加載失敗的Drawable
}
@Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
// 設置加載成功的Bitmap
}
@Override
public void onLoadCleared(Drawable placeholder) {
// 設置加載被取消時的Drawable
}
@Override
public void getSize(SizeReadyCallback cb) {}
@Override
public void setRequest(Request request) {}
@Override
public Request getRequest() {
return null;
}
@Override
public void onStart() {}
@Override
public void onStop() {}
@Override
public void onDestroy() {}
});
// 指定期望的圖片大小,返回一個Bitmap對象,要在子線程中獲取,我覺得這個可以在應用使用,比如在主頁我需要顯示這個圖片,我可以在歡迎頁面加載這個圖片,到了主頁可以直接使用,至於為何要在線程中使用,有待研究。
into(int w, int h);
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = Glide.with(context)
.load(url)
.into(200, 200)
.get();
}
}).start();
除了with(),load(),into()三個基本的方法,Glide還有很多使用的Api,下面一一道來。
2.設置bitmap或者gif
.asBitmap();
.asGif();
這兩句話,有時候不設置是可以的,但是有時候配合其他屬性一起設置的時候,如果沒有這個屬性的話,其他屬性無法實現,所以大家還是規范一些,寫完整些。
3.設置圖片大小
.override(int w, int h);
指定加載bitmap的大小,比如原圖是500 x 500,into(100, 100),加載出的bitmap就是100 x 100,這樣就可以適配各種所需的UI大小,Glide已經為你做好了比例縮放,經過我的試驗,如果圖片是720 x 1280,將其設置成720 x 500,該圖片將會以500這個尺寸比例縮放。
Glide.with(this).load(R.mipmap.login).asBitmap().override(720, 500).into(imageView);
4.加載縮略圖
thumbnail(0.1f);
它是在你into的view中先加載設置的縮略圖,然後才會加載大圖,注:參數范圍為0~1。
5.設置占位圖或者加載錯誤圖:
.placeholder(R.drawable.placeholder)
.error(R.drawable.imagenotfound)
在實際項目中,為了優化顯示,比如頭像在下載過程中,會使用一張默認的圖片先在UI上面顯示,則用placeholder,若加載成功,則顯示下載圖片,否則就顯示加載失敗的圖片,使用error。
6.加載完成動畫
.animate(Animator animator);//或者int animationId
初次加載出Bitmap時展示的動畫,可以是屬性動畫,也可以是Tween動畫,可以是加載代碼動畫,也可以是動畫資源文件,方便的很。
注:這個動畫只在初次加載出來時使用,已經加載過了,下載再從緩存中取是不會動畫的。
7.圖片適配scaleType
.centerCrop(); // 長的一邊撐滿
.fitCenter(); // 短的一邊撐滿
8.暫停\回復請求
Glide.with(context).resumeRequests();
Glide.with(context).pauseRequests();
當列表在滑動的時候,調用pauseRequests()取消請求,滑動停止時,調用resumeRequests()恢復請求。
9.在後台線程當中進行加載和緩存
downloadOnly(int width, int height)
downloadOnly(Y target)// Y extends Target
into(int width, int height)
Glide的downloadOnly()是將Image的二進制文件下載到硬盤緩存當中,以便在後續使用,可以在UI線程當中異步下載,也可以在異步線程當中同步調用下載,值得注意的是,如果在同步線程當中,
downloadOnly使用一個target作為參數,而在異步線程當中則是使用width和height。
在後台線程當中下載圖片,可以通過如下的方式:
new Thread(new Runnable() {
@Override
public void run() {
FutureTarget future = Glide.with(applicationContext)
.load(yourUrl)
.downloadOnly(500, 500);
File cacheFile = future.get();
}
}).start();
上面的調用只能在異步線程當中,如果在main Thread當中調用.get(),會阻塞主線程,會導致Crash。
這個其實就是可以獲取該Image的緩存路徑,目前還沒想好怎麼封裝一個獲取緩存路徑的通用類,有待研究。至於Glide的緩存策略,這裡也簡要介紹下,也是配置:
緩存策略
.diskCacheStrategy(DiskCacheStrategy.ALL) //這個是設置緩存策略。
DiskCacheStrategy.NONE:不緩存
DiskCacheStrategy.SOURCE:緩存原始圖片
DiskCacheStrategy.RESULT:緩存壓縮過的結果圖片
DiskCacheStrategy.ALL:兩個都緩存
10.轉換器
第七點中的centerCrop和fitCenter是Glide默認的兩種轉換器,現在已經有了Glide集成庫,提供各式各樣的Api可以將圖片轉為各種形狀,例如圓形,圓角型等等,庫呢在上面已經介紹過啦,下面就來使用這些庫看看效果。
(1)單獨轉換器效果(毛玻璃為例)
Glide.with(this).load(R.mipmap.login).bitmapTransform(new BlurTransformation(this, 20)).into(imageView);
可以看到毛玻璃效果,BlurTransformation就是庫提供的類,20這個數字是毛玻璃的模糊程度設置,注意范圍是1~25,否則圖片將不會顯示出來。
(2)復合轉換器效果
Glide.with(this).load(R.mipmap.login).bitmapTransform(new BlurTransformation(this, 20), new CropCircleTransformation(this)).into(imageView);
可以看到,圖片不僅變成毛玻璃,還變成了圓形。
我們可以來看看bitmapTransform這個方法:
public DrawableRequestBuilder bitmapTransform(Transformation... bitmapTransformations) {
GifBitmapWrapperTransformation[] transformations =
new GifBitmapWrapperTransformation[bitmapTransformations.length];
for (int i = 0; i < bitmapTransformations.length; i++) {
transformations[i] = new GifBitmapWrapperTransformation(glide.getBitmapPool(), bitmapTransformations[i]);
}
return transform(transformations);
}
可以通過看代碼發現,bitmapTransform這個方法可以傳入多種轉換器,實現不同的效果,變通性很強。
下面我來列一下多種Transformations,具體的我也不展示了,留給大家去嘗試:
Crop
默認:CropTransformation,
圓形:CropCircleTransformation,
方形:CropSquareTransformation,
圓角:RoundedCornersTransformation
Color
顏色覆蓋:ColorFilterTransformation,
置灰:GrayscaleTransformation
Blur
毛玻璃:BlurTransformation
Mask
還未弄明白:MaskTransformation
嘗試完這些,你就可以發現Glide的強大之處!
當然,除了上面庫提供的這些,還可以自定義轉換器。
第一步、編寫轉換器類
繼承BitmapTransformation:
private static class MyTransformation extends BitmapTransformation {
public MyTransformation(Context context) {
super(context);
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform,
int outWidth, int outHeight) {
Bitmap myTransformedBitmap = ... // 在這裡自定義圖片轉換,跟平時自己裁剪截圖什麼的一樣
return myTransformedBitmap;
}
@Override
public String getId() {
// Return some id that uniquely identifies your transformation.
return "com.example.myapp.MyTransformation";
}
}
第二步、在Glide方法鏈當中用.transform(…)替換fitCenter()/centerCrop()
Glide.with(context)
.load(Url)
.transform(new MyTransformation(context))
.into(imageView);
在上面使用過程當中沒有設置尺寸值,那麼轉換器轉換的圖片尺寸怎麼確定呢,Glide實際上已經足夠智能根據view的尺寸來確定轉換圖片的尺寸了,如果需要自定義尺寸,而不是用view和target當中的尺寸,那麼可以使用override(int,int)設置相關的寬和高。
前言Android開發中使用頂部 & 底部Tab導航欄的頻次非常高,主要的實現手段有以下:TabWidget 隱藏TabWidget,使用RadioGroup和R
前提條件:已經安裝了JDK 6.0、android SDK、NDK r9和eclipsele4.2開發環境.推薦下載Android開發的綜合套件adt-bundle-wi
在android的應用層中,涉及到很多應用框架,例如:Service框架,Activity管理機制,Broadcast機制,對話框框架,標題欄框架,狀態欄框架,通知機制,
接著上一篇博客,上一篇博客跟大家分享了三種開始頁面的定時跳轉,根據項目需求接下來就說一下向導頁面吧!幾乎每一個APP都有自己的向導頁面,一般都是第一次安裝的時或者第一次進