Android圖片加載框架Picasso最全使用教程 三

前面我們對Picasso的用法有了一定得了解,下面就分析一下一些特殊情況下,Picasso的用法.

調用.noFade()

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

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .placeholder(R.mipmap.ic_launcher)  
    .error(R.mipmap.future_studio_launcher)  
    .noFade()
    .into(imageViewFade);

調用.noPlaceholder()

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

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .placeholder(R.mipmap.ic_launcher)  
    .into(imageViewNoPlaceholder, new Callback() {
        @Override
        public void onSuccess() {
            // 當上次加載完成後,進行二次加載
            Picasso
                .with(context)
               .load(UsageExampleListViewAdapter.eatFoodyImages[1])
               .noPlaceholder() 
               .into(imageViewNoPlaceholder);
        }

        @Override
        public void onError() {

        }
    });

調用resize(x, y)來自定義圖片的加載大小

如果圖片很大或者想自定義圖片的顯示樣式,可以調用該API來解決這個問題;

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(600, 200)  
    .into(imageViewResize);

調用`onlyScaleDown()來縮短圖片的加載計算時間

如果我們調用了resize(x,y)方法的話,Picasso一般會重新計算以改變圖片的加載質量,比如一張小圖變成一張大圖進行展示的時候,但是如果我們的原圖是比我們從新resize的新圖規格大的時候,我們就可以調用onlyScaleDown()來直接進行展示而不再重新計算.

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(6000, 2000)
    .onlyScaleDown() // 如果圖片規格大於6000*2000,將只會被resize
    .into(imageViewResizeScaleDown);

對拉伸圖片的處理

如果圖片被操作了,可能在展示的時候就會比較醜,我們是想改變這種情景的,Picasso給我們提供了兩種選擇進行圖片展示,centerCrop() 或者 centerInside().

  • centerCrop() - 圖片會被剪切,但是圖片質量看着沒有什麼區別

  • Inside()- 圖片會被完整的展示,可能圖片不會填充滿ImageView`,也有可能會被拉伸或者擠壓

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(600, 200)
    .centerInside() 或者調用 .centerCrop()
    .into(imageViewResizeCenterInside);

調用.fit()來智能展示圖片

如果調用了該API, Picasso會對圖片的大小及ImageView進行測量,計算出最佳的大小及最佳的圖片質量來進行圖片展示,減少內存,並對視圖沒有影響;

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .fit()
    .into(imageViewHero);

調用.priority()設置圖片加載的優先級

如果一個屏幕上頂部圖片較大,而底部圖片較小,因爲Picasso是異步加載,所以小圖會先加載出來,但是對於用戶來說,更希望看到的是上面的圖片先加載,底部的圖片後加載,Picasso支持設置優先級,分爲HIGH, MEDIUM, 和 LOW,所有的加載默認優先級爲MEDIUM;

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .fit()
    .priority(Picasso.Priority.HIGH)
    .into(imageViewHero);

注意:設置優先級並不能保證圖片就一定會被優先加載,只是會偏向傾斜於先加載;

調用tag()爲請求添加標記提升用戶體驗

  我們都知道,在一個ListView的子item中加載一張圖片是很常見的,這些圖片都來源於網絡請求,如果這個listview有上千條數據,當用戶快速滑動的時候,每個item會不斷的被複用,當然Picasso的請求也不斷地進行請求,取消請求,再次請求,再次取消的操作(對屏幕外的自動取消請求),但是如果有一個方案,可以在用戶在快速滑動的時候全部停止請求,只有在滑動停止時再去請求,就非常完美了;

Picasso提供了三種設置Tag的方式

  • 暫停標記 pauseTag()
  • 可見標記 resumeTag()
  • 取消標記 cancleTag()

pauseTag()resumeTag()的用法

在圖片請求時添加標記

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .tag("Profile ListView") //參數爲 Object
    .into(imageViewWithTag);

然後讓listview實現滑動監聽

@Override
  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("Profile ListView");
    } else {
          picasso.pauseTag("Profile ListView");
    }
  }

cancleTag()的使用場景

試想一下,當你在瀏覽購物車的時候,這個時候就會去展示所有被選中item的圖片資源,如果這個時候用戶點擊了購買按鈕,就會彈出一個progressdialog去請求數據以進行頁面跳轉,這個時候原來的請求就需要取消掉了;

public void buyButtonClick(View v) {
     showDiaolg();

    // 取消網絡請求
    Picasso
        .with(context)
        .cancelTag("ShoppingCart");
}

注意:如果tag狀態爲pause或者resume的話,Picasso會對tag持有一個引用,如果此時用戶退出了當前Activity,垃圾回收機制進行回收的時候,就會出現內存泄露,所以需要在onDestory()方法中進行相應處理;

.fetch() , .get()Target之間的區別

  • .fetch() - 該方法會在後臺異步加載一張圖片,但是不會展示在ImageView上,也不會返回Bitmap,這個方法只是爲了將獲取到的資源加載到本地和內存中,爲了後期加載縮短時間;
  • .get() - 該方法也是一個異步線程,不過加載完成後會返回一個Bitmap,但是需要注意,該方法不能在主線程中調用,因爲會造成線程阻塞;
  • Target - 我們之前調用.into()方法,只是將獲取到的資源加載到ImageView中,但我們還可以將資源作爲回調放到Target中,上代碼:
private Target target = new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        //加載成功後會得到一個bitmap,可以自定義操作
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) {
        // 加載失敗進行相應處理
    }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {

    }
};

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .into(target);

注意:你可以使用.get()或者Target獲取圖片的Bitmap,但是當你使用Target時,不能使用匿名內部類的方式,因爲垃圾回收機制在你獲取不到Bitmap的時候會把對象回收;

Picasso在自定義Notifications上的使用

Picasso有一個功能是可以加載圖片到RemoteViews上,而RemoteViews是用在Widgets及自定義notification佈局上的,下面通過一個小的示例來看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);
    }

上面可以看到,Picasso的使用也是非常簡單,只需要調用.into()的另一個重載方法即可:
.into(android.widget.RemoteViews remoteViews, int viewId, int notificationId, android.app.Notification notification)

效果如下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章