Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 圖片顯示框架(二)

圖片顯示框架(二)

編輯:關於Android編程

框架詳解

Android-Universal-Image-Loader

一、特點
多線程的圖像加載
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)設置相關的寬和高。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved