Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發之圖片加載緩存框架Picasso的領教

Android開發之圖片加載緩存框架Picasso的領教

編輯:關於Android編程

Picasso是Square公司開源的一個Android圖形緩存庫,官方網址:http://square.github.io/picasso/ Picasso實現了圖片的異步加載,並解決了Android中加載圖片時常見的一些問題,它有以下特點:
  • 在Adapter中取消了不在視圖范圍內的ImageView的資源加載,因為可能會產生圖片錯位;
  • 使用復雜的圖片轉換技術降低內存的使用。
  • 自帶內存和硬盤的二級緩存機制。
  • 內部也是集成LRU(近期最少使用)算法。
Picasso采用OkHttpClient進行網絡請求的,並將圖片存到/data/data//cache/picasso-cache內部存儲空間裡,開辟的空間大小最小是5兆最大是50兆,這些都是從源碼看出來的,同時采用Lru算法來進行移除不常用的圖片減少內存空間占有提高利用率。Picasso默認開啟三個線程進行本地與網絡之間的訪問。加載圖片的順序是 內存->本地->網絡。   將Picasso添加到項目中: 目前Picasso的最新版本是2.5.2,你可以下載對應的Jar包,將Jar包添加到你的項目中,或者在build.gradle配置文件中加入
compile 'com.squareup.picasso:picasso:2.5.2'
注意如果你開啟了混淆,你需要將以下代碼添加到混淆規則文件中:
-dontwarn com.squareup.okhttp.**
  基本使用方法: Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); Picasso.with(context).load(new File(...)).into(imageView3); 高級使用方法: 1.添加加載中占位圖和加載失敗占位圖
Picasso .with(context)
               .load(imageUrl)
               .placeholder(R.mipmap.ic_launcher)              //添加占位圖片
               .error(R.mipmap.ic_launcher)                          //加載失敗顯示的圖片
               .into(imageView);
也可判斷加載結果是否成功:

Picasso.with(this).load(userPhotoUrl).into(user_photo, new Callback() { @Override public void onSuccess() { //加載成功 } @Override public void onError() { //加載失敗 } });

 

2.調用.noFade()。Picasso的默認圖片加載方式有一個淡入的效果,如果調用了noFade(),加載的圖片將直接顯示在ImageView上

Picasso .with(context)
               .load(imageUrl)
               .placeholder(R.mipmap.ic_launcher)              //添加占位圖片
               .error(R.mipmap.ic_launcher)                          //加載失敗顯示的圖片
               .noFade()                                                          // 去除淡入效果
               .into(imageView);

 

3.調用.noPlaceholder()。有一個場景,當你從網上加載了一張圖片到Imageview上,過了一段時間,想在同一個ImageView上展示另一張圖片,這個時候你就會去調用Picasso,進行二次請求,這時Picasso就會把之前的圖片進行清除,可能展示的是.placeholder()的圖片,如果你沒有設置占位圖,則請求的過程中將會是一片空白,給用戶並不是很好的體驗,如果調用了noPlaceholder(),就不會出現這種情況.

Picasso .with(context)
               .load(imageUrl)
               .noPlaceholder(R.mipmap.ic_launcher)              //去除占位圖
               .into(imageView);
  4.調用resize(x, y)。自定義圖片的加載大小
Picasso .with(context)
               .load(imageUrl)
               .resize(600,200)             //自定義圖片的加載大小
               .into(imageView);
 

 

5.調用onlyScaleDown()。一般.resize(x,y)會將加載的圖片的重新計算然後按照設定展示出來。如果我們加載的圖片的尺寸比.resize(x,y)的尺寸還大,此時調用.onlyScaleDown()將會直接將圖片按照.resize(x,y)的尺寸展示出來,效率提高了圖片的加載時間。

 
Picasso .with(context)
               .load(imageUrl)
               .resize(600,200)             //自定義圖片的加載大小
               .onlyScaleDown()         //效率提高圖片的加載時間配合resize(x,y)使用。           
               .into(imageView);
 

 

6.針對拉伸圖片的處理。Picasso給我們提供了兩種進行圖片拉伸的展示方式,視情況選擇,避免圖片拉伸變形難看。

centerCrop() - 圖片會根據最短邊進行多余剪切,但是圖片質量看著沒有什麼區別。 Inside()- 圖片會被完整的展示,圖片過小使圖片不會填充滿ImageView`,圖片過大則會硬填充到view中,圖片此時出現變形。
Picasso .with(context)
               .load(imageUrl)
               .resize(600,200)             //自定義圖片的加載大小
               .centerCrop()               //填充居中裁剪顯示
               .into(imageView);
 

 

7.調用.fit()。Picasso會對圖片的大小及ImageView進行測量,計算出最佳的大小及最佳的圖片質量來進行圖片展示,減少內存,並對視圖沒有影響;

 
Picasso .with(context)
               .load(imageUrl)
               .fit()
               .into(imageView);

 

8.調用.priority()。設定圖片加載的優先級。通常情況我們進行網絡加載圖片時一般是哪個圖片小就先把那個圖片先加載出來。有些時候我們想讓圖片按照某個順序或者等級加載圖片,Picasso為我們提供了三種圖片加載的優先級:HIGH, MEDIUM, LOW。所有的加載默認優先級為MEDIUM。

Picasso .with(context)
               .load(imageUrl)
               .fit()
               .Priority(Picasso.Priority.HIGH)    //設定圖片加載的優先級
               .into(imageView);

 

9.調用.tag()。控制圖片的加載暫停或取消。

Picasso提供了三種設置Tag的方式 暫停標記 pauseTag() 可見標記 resumeTag() 取消標記 cancleTag()
Picasso .with(context)
               .load(imageUrl)
               .tag("PICASSO_TAG")
               .into(imageView);
針對listView(),有些時候我們想在滑動的時候不加載圖片,滑動結束的時候在進行加載我們可以重寫下邊的這個方法。
public void onScrollStateChanged(AbsListView view, int scrollState) {
         final Picasso picasso = Picasso.with(context)} 
         if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
               picasso.resumeTag("PICASSO_TAG");
         } else {
              picasso.pauseTag("PICASSO_TAG");
         }
 }
有些時候我們針對當前的請求需要中斷:
Picasso .with(context)
              .cancelTag("PICASSO_TAG");
  10.指定Target。我們之前調用.into()方法,只是將獲取到的資源加載到ImageView中,但我們還可以將資源作為回調放到Target中。但是這裡的target不能作為匿名內部類直接引用,即不能在.into()裡直接new出來,因為垃圾回收機制在你獲取不到Bitmap的時候會把對象回收。 Picasso下載圖片  
private void download() {
        //獲得圖片的地址
        String url = mList.get(mPosition);
        //Target
        Target target = new Target(){
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                String imageName = System.currentTimeMillis() + ".png";
                File dcimFile = FileUtil
                        .getDCIMFile(FileUtil.PATH_PHOTOGRAPH,imageName);        
                FileOutputStream ostream = null;
                try {
                    ostream = new FileOutputStream(dcimFile);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                    ostream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Toast.makeText(PicActivity.this,"圖片下載至:"+dcimFile,Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onBitmapFailed(Drawable errorDrawable) {
            }
            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {
            }
        };
        //Picasso下載
        Picasso.with(this).load(url).into(target);
    }
  11.自定義通知欄采用Picasso加載圖片。

private void testRemoteView() { RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.item_picasso); remoteViews.setImageViewResource(R.id.iv_remoteview, R.mipmap.abc); remoteViews.setTextViewText(R.id.tv_title, "This Title"); remoteViews.setTextViewText(R.id.tv_desc, "This desc"); remoteViews.setTextColor(R.id.tv_title, getResources().getColor(android.R.color.black)); remoteViews.setTextColor(R.id.tv_desc, getResources().getColor(android.R.color.holo_blue_bright)); NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this) .setSmallIcon(R.mipmap.notifation) .setContentTitle("Context Title") .setContentText("Content Text") .setContent(remoteViews) .setPriority(NotificationCompat.PRIORITY_MIN); Notification notification = builder.build(); if (Build.VERSION.SDK_INT > 16) { notification.bigContentView = remoteViews; } NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIFICATION_ID, notification); Picasso.with(MainActivity.this) .load("http://www.jycoder.com/json/Image/3.jpg") .into(remoteViews, R.id.iv_remoteview, NOTIFICATION_ID, notification); }

 

12.圖片旋轉

a.根據自身中心旋轉:


Picasso .with(context) .load(imageUrl) .rotate(90f) //旋轉90度 .into(imageView);
b.根據某個點旋轉:



Picasso .with(context) .load(imageUrl) .rotate(45f, 200f, 100f) //以中心點(200,100)旋轉45度。 .into(imageView);

 

13.Picasso對圖片的轉化(Transformation擴展)。

先了解一下Transformation這個類,這是一個接口,裡面有兩個方法,其中transForm這個方法最重要,負責對Bitmap的轉換操作。

publicinterface Transformation { //對Bitmap進行轉換操作 Bitmap transform(Bitmap source); //一個key 主要是緩存的key的生成和它有關 String key(); }
a.將加載完成的圖片做成圓形:

public class CircleTransform implements Transformation { @Override public Bitmap transform(Bitmap source) { //獲取最小邊長 int size=Math.min(source.getWidth(),source.getHeight()); //獲取圓形圖片的寬度和高度 int x=(source.getWidth()-size)/2; int y=(source.getHeight()-size)/2; //創建一個正方形區域的Btimap Bitmap squaredBitmap=Bitmap.createBitmap(source,x,y,size,size); if(squaredBitmap!=source){ source.recycle(); } //創建一張可以操作的正方形圖片的位圖 Bitmap bitmap=Bitmap.createBitmap(size,size,source.getConfig()); //創建一個畫布Canvas Canvas canvas=new Canvas(bitmap); //創建畫筆 Paint paint=new Paint(); BitmapShader shader=new BitmapShader(squaredBitmap,BitmapShader.TileMode.CLAMP,BitmapShader.TileMode.CLAMP); paint.setShader(shader); paint.setAntiAlias(true); //圓形半徑 float r=size/2f; canvas.drawCircle(r,r,r,paint); squaredBitmap.recycle(); return bitmap; } @Override public String key() { return "circle"; } }
調用:

Picasso.with(context) .load(UsageExampleListViewAdapter.eatFoodyImages[0]) .transform(new CircleTransform()) .into(imageViewTransformationBlur);
b.模糊一張圖片

public class BlurTransformation implements Transformation { RenderScript rs; public BlurTransformation(Context context) { super(); rs = RenderScript.create(context); } @Override public Bitmap transform(Bitmap bitmap) { // 創建一個Bitmap作為最後處理的效果Bitmap Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); // 分配內存 Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED); Allocation output = Allocation.createTyped(rs, input.getType()); // 根據我們想使用的配置加載一個實例 ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setInput(input); // 設置模糊半徑 script.setRadius(10); //開始操作 script.forEach(output); // 將結果copy到blurredBitmap中 output.copyTo(blurredBitmap); //釋放資源 bitmap.recycle(); return blurredBitmap; } @Override public String key() { return "blur"; } }



調用:

Picasso.with(context) .load(UsageExampleListViewAdapter.eatFoodyImages[0]) .transform(new BlurTransformation(Context)) .into(imageViewTransformationBlur);
c.實現圓形模糊圖片:


List transformations = new ArrayList<>(); transformations.add(new new CircleTransform()); transformations.add(new BlurTransformation(context)); Picasso.with(context) .load(UsageExampleListViewAdapter.eatFoodyImages[0]) .transform(transformations) .into(imageViewTransformationBlur);


 

14.調用.memoryPolicy()。

memoryPolicy主要用於Picasso對內存的管理。有兩個枚舉類: NO_CACHE - 讓Picasso跳過從內存中讀取圖片這一操作 NO_STORE - 如果你的圖片只加載一次就沒用了,就調用該值,這樣的話Picasso就不會在內存及本地進行緩存了。
Picasso  
    .with(context)
    .load(url)
    .memoryPolicy(MemoryPolicy.NO_CACHE)
    .into(imageViewFromDisk);
Picasso  
    .with(context)
    .load(url)
    .memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)
    .into(imageViewFromDisk);

 

15.調用.networkPolicy()。

networkPolicy和memoryPolicy類似,前者是對內存管理後者是對存儲空間管理。有三個枚舉類: NO_CACHE - 讓Picasso跳過從本地讀取資源這一過程 NO_STORE - 讓Picasso不進行本地圖片緩存 OFFLINE - 讓Picasso加載圖片的時候只從本地讀取除非聯網正常並且本地找不到資源的情況下進行網絡請求。
Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork);
或配合memoryPolicy一起使用:
Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork); 

 

16.調用.setIndicatorsEnabled(true),查看圖片來源。

興許加載圖片的時候我們不知道加載的圖片是從內存加載出來還是從本地加載出來的還是直接從網絡上加載出來的,這時候我們調用.setIndicatorsEnabled(true)會在圖片的左上角出現一個有顏色的小三角幫助我們區分,總共有三種顏色: 藍色 - 從內存中獲取,是最佳性能展示 綠色 - 從本地獲取,性能一般 紅色 - 從網絡加載,性能最差
Picasso  
    .with(context)
    .setIndicatorsEnabled(true);
然後在進行加載圖片就可以看到每張圖片的來源了
Picasso  
    .with(context)
    .load(url)
    .into(imageViewFromDisk);

 

17.調用.setLoggingEnabled(true)。用來查看每張圖片加載出來的用時多少,日志在控制台裡打出來。

Picasso  
    .with(context)
    .setLoggingEngabled(true);
然後再進行加載圖片就可以看到每張圖片的日志了
Picasso  
    .with(context)
    .load(url)
    .into(imageViewFromDisk);
 

 

18.整體加載分析StatsSnapshot。有些時候我們想看我們加載了這麼多張圖片後圖片內存占用多少,可以采用StatsSnapshot.

StatsSnapshot picassoStats = Picasso.with(context).getSnapshot();
然後打印日志:
Log.d("Picasso Stats", picassoStats.toString());
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved