2015年12月14日 星期一

Picasso 开源项目使用教程

also can use http://frescolib.org/docs/index.html

copy from:http://xiazdong.me/2014/10/03/picasso-tutorial/


Picasso 開源項目使用教程

前言

圖片加載是Android 開發經常要實現的功能,而這也是談到Android 性能優化問題時不得不提的問題,而Picasso 項目就是幫助我們解決這個問題的,而我在網上搜也沒找到比較全面關於Picasso的中文教程,因此這裡就寫一篇關於Picasso 這個開源項目的介紹。

Picasso 基本介紹

  • 項目地址:https://github.com/square/picasso
  • 項目定位:A powerful image downloading and caching library for Android,即實現圖片加載、圖片緩存的功能。
  • 該項目的依賴項目有:okHttp, okHttp-urlConnection, okio。如果通過jar包方式添加則需要注意版本,本文用的版本是:Picasso 2.3.4, okHttp 2.0.0, okHttp-urlConnection 2.0.0, okio 1.0.0;如果通過gradle 添加那麼依賴就自動添加進來了。
  • 很多人會把它和UIL 項目比較,如果你剛剛接觸圖片異步加載,則我比較推薦Picasso,因為使用起來太方便了。

優點

1、入門簡單:一般為了實現一個圖片異步加載的功能,少說必須要使用:AsyncTask, LruCache, DiskCache, BitmapFactory等等,實現起來還是有難度的,但是Picasso只需要一行代碼即可實現圖片異步加載:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
是不是非常方便。
2、自動取消Adapter的下載任務:一般來說我們在實現ListView時會重用view,比如第10個位置的view重用第1個位置的view,當從第1個位置快速滑到第10個位置時,雖然第1個位置的圖片還沒下載好,Picasso能夠幫我們自動取消第1個位置的下載任務,開始第10個位置的下載任務,我們只需要管業務邏輯即可。
3、利用最少的內存對圖片進行變換:簡單的API即可實現圖片的旋轉、改變大小等簡單變換,還能夠自定義變換。
4、自動進行內存和磁盤的緩存 :不需要自己實現緩存(缺點是不能設定緩存大小),當然你在加載圖片時也可以設置成不使用緩存(skipMemoryCache)。
5、提供很好的調試界面:如果開啟調試模式,則如果圖片是從網絡中獲得,則圖片左上角會有紅色三角形;如果圖片從磁盤獲得,則圖片左上角會有黃色三角形;如果圖片從內存獲得,則圖片左上角會有綠色三角形。如圖所示: 
6、支持通過資源id、本地文件、網絡載入圖片 : load()函數即可實現從不同的來源載入圖片。

基本使用方法

一般我遇到的需要實現的功能就是三個:
  • 簡單實現異步加載圖片到ImageView,並在圖片加載成功或失敗時有個回調,即當圖片加載成功時可以自定義一些操作,當圖片加載失敗時可以自定義一些操作。
  • 下載圖片並保存到本地。
  • 對加載的圖片進行變換。
接下去我將會介紹常用的一些函數。

1、加載圖片到ImageView

ImageView  view  =  null ; 
Picasso  picasso  =  Picasso . with ( this ); 
picasso . setIndicatorsEnabled ( true );    //開啟調模式,它能夠在圖片左上角顯示小三角形,這個小三角形的顏色標明了圖片的來源:網絡、內存緩存、磁盤緩存
picasso . setLoggingEnabled ( true );   //打開日誌,即log中會打印出目前下載的進度、情況
picasso . load ( "http://xxx.jpg" )     //可以是本地圖片或網絡圖片
       . placeholder ( R . drawable . placeholder )    //當圖片正在加載時顯示的圖片(optional) 
       . error ( R . drawable . error )            //當圖片加載失敗時顯示的圖片(optional) 
       . into ( view ,  new  Callback ()  {    //將圖片下載完後放進view中,回調是可選的
           @Override 
           public  void  onSuccess ()  { 
               //加載圖片成功時回調
           } 
           @Override 
           public  void  onError ()  { 
               //加載圖片失敗時回調
           } 
       });

2、加載圖片並自定義動作

Target  target  =  new  Target (){ 
      @Override 
      public  void  onBitmapLoaded ( Bitmap  bitmap ,  Picasso . LoadedFrom  loadedFrom )  { 
             //當圖片加載成功時調用,bitmap是加載的圖片,loadFrom標明圖片的來源是網絡、內存還是磁盤
             / /可以在裡面執行把圖片保存到本地的操作
      } 
      @Override 
      public  void  onBitmapFailed ( Drawable  errorDrawable )  {    //當圖片加載失敗時調用
      } 
      @Override 
      public  void  onPrepareLoad ( Drawable  placeHolderDrawable )  {     //當任務被提交時調用
      } 
}; 
picasso . load ( new  File ( "/1.jpg" )). into ( target );  //指定target任務加載圖片

3、對圖片進行變換

Transformation  transformation  =  new  Transformation ()  { 
     @Override 
     public  Bitmap  transform ( Bitmap  bitmap )  { 
        Bitmap  newBitmap  =  null ; 
        //自定義變換
        if ( bitmap  !=  null  &&  ! ​​bitmap . isRecycled ()){    //將舊圖片回收
            bitmap . recycle (); 
        } 
        return  newBitmap ; 
     }

     @Override 
     public  String  key ()  {  //將用作cache的key 
        return  "key" ; 
     } 
}; 
picasso . load ( R . drawable . download ) 
           . skipMemoryCache ()  //不要把加載的圖片放入緩存,也不要從緩存中取圖片
        . transform ( transformation )     //執行自定義變換
        . into ( view );

案例: 實現異步加載圖片的ListView

效果如下:
我們使用到了通用適配器技術(實現代碼為CommonAdapter項目),使得我們的主要代碼只有30+行:
public  class  SimpleListActivity  extends  Activity  {

    @Override 
    protected  void  onCreate ( Bundle  savedInstanceState )  { 
        super . onCreate ( savedInstanceState ); 
        setContentView ( R . layout . activity_simple_list ); 
        List < DataItem >  datas  =  getSampleDatas (); 
        ListView  listView  =  ( ListView ) findViewById ( R . id . list ) ; 
        Picasso . with ( this ). setIndicatorsEnabled ( true ); 
        listView . setAdapter ( new  CommonAdapter < DataItem >( this , datas , R . layout . item_list )  { 
            @Override 
            public  void  convert ( ViewHolder  holder ,  DataItem  item , int  position )  { 
                holder . setText ( R . id . text , item . name ); 
                holder . setImage ( R . id . image , item . url , null );   //setImage函數中使用了Picasso庫
            } 
        }); 
    }

    private  List < DataItem >  getSampleDatas ()  { 
        List < DataItem >  datas  =  new  ArrayList < DataItem >(); 
        String []  urls  =  getResources (). getStringArray ( R . array . urls ); 
        for ( int  i  =  0 ;  i  <  urls . length ;  i ++){ 
            DataItem  item  =  new  DataItem ( urls [ i ], urls [ i ]); 
            datas . add ( item ); 
        } 
        return  datas ; 
    } 
}

class  DataItem { 
    String  url ; 
    String  name ; 
    public  DataItem ( String  url ,  String  name ){ 
        this . url  =  url ; 
        this . name  =  name ; 
    } 
}

參考文獻