Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中使用ImageLoader加載圖片

Android中使用ImageLoader加載圖片

編輯:關於Android編程

Android上讓人頭疼的莫過於從網絡上獲取圖片,然後顯示圖片,最後還要考慮到圖片的回收問題,這之間只要有任何一個環節有問題都可能直接OOM。尤其在需要展示圖片的列表頁面,會加載大量網絡上的圖片,每當快速滑動列表的時候,都會很卡,甚至會因為內存溢出而崩潰。

這時就是ImageLoader的 show time
了。ImageLoader的目的是為了實現異步的網絡圖片加載、緩存及顯示,支持多線程異步加載。


ImageLoader在GitHub的下載地址:https://github.com/nostra13/Android-Universal-Image-Loader。


ImageLoader的工作原理是這樣的:在顯示圖片的時候,它會先在內存中查找;如果沒有,就去本地查找;如果還沒有,就開一個新的線程去下載這張圖片,下載成功會把圖片同時緩存到內存和本地。
基於這個原理,我們可以在每一次退出一個頁面的時候,把ImageLoader內存中的緩存全都清除,這樣就節省了大量內存,反正下次再用到的時候從本地再取出來就是了。
此外,由於ImageLoader對圖片是軟引用的形式,所以內存中的圖片會在內存不足的時候被系統回收(內存足夠的時候不會對其進行垃圾回收)。

上面說到了ImageLoader的設計原理,下面來說ImageLoader的使用。

ImageLoader的三大組件:

ImageLoaderConfiguration——對圖片緩存進行總體配置,包挎內存緩存的大小、本地緩存的大小和位置、日志、下載策略(FIFO還是LIFO)等等。 ImageLoader——我們一般使用displayImage來把URL對應的圖片顯示在ImageView上。 ImageLoaderOptions——在每個頁面需要顯示圖片的地方,控制如何顯示的細節,比如指定下載時的默認圖(包括下載中、下載失敗、URL為空等),是否將緩存放到內存或者本地磁盤。

在這裡,從我正在研讀的一本書上借用一段話描述以上三者的關系。書中的這段話也是引用了博客園上陳哈哈的博文。原文如下:

===========================================
他們有點像廚房規定、廚師、客戶個人口味之間的關系。ImageLoaderConfiguration就像是廚房裡面的規定,每一個廚師要怎麼著裝,要怎麼保持廚房的干淨,這是針對每一個廚師都適用的規定,而且不允許個性化改變。ImageLoader就像是具體做菜的廚師,負責具體菜譜的制作。DisplayImageOptions就像是每個客戶的偏好,根據客戶是重口味還是清淡,每一個ImageLoader根據DisplayImageOptions的要求具體執行。


下面就開始給大家講講怎麼使用ImageLoader:

1、重寫application,並初始化配置

public class AppContext extends Application {

    /**
     * Called when the application is starting, before any activity, service, or
     * receiver objects (excluding content providers) have been created.
     * (當應用啟動的時候,會在任何activity、Service或者接收器被創建之前調用,所以在這裡進行ImageLoader 的配置)
     * 當前類需要在清單配置文件裡面的application下進行name屬性的設置。
     */
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        // 緩存圖片的配置,一般通用的配置
        initImageLoader(getApplicationContext());
    }

    private void initImageLoader(Context context) {
        // TODO Auto-generated method stub
        // 創建DisplayImageOptions對象
        DisplayImageOptions defaulOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true).cacheOnDisk(true).build();
        // 創建ImageLoaderConfiguration對象
        ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(
                context).defaultDisplayImageOptions(defaulOptions)
                .threadPriority(Thread.NORM_PRIORITY - 2)
                .denyCacheImageMultipleSizesInMemory()
                .diskCacheFileNameGenerator(new Md5FileNameGenerator())
                .tasksProcessingOrder(QueueProcessingType.LIFO).build();
        // ImageLoader對象的配置
        ImageLoader.getInstance().init(configuration);
    }

}

在使用ImageLoader的實例之前,你需要初始化該配置,否則會報初始化錯誤。一般我們直接寫在application中初始化。
在初始化配置完成後,在清單配置文件中寫入你自定義的application,並寫入訪問權限。如下圖所示:

這裡寫圖片描述

到這裡基本的配置就完了,接下來就是加載圖片了。


2、在使用ImageView加載圖片的地方,配置當前頁面的ImageLoader選項。有可能是Activity,也有可能是Adapter。我這個demo是在adapter裡面配置DisplayImageOptions對象。代碼如下所示:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public class MainActivity extends Activity { // 創建ImageLoader對象 private ImageLoader imageLoader = ImageLoader.getInstance(); private ListView lsv_image_loader; // 網絡圖片的URL和drawable下的圖片,其他的圖片(比如手機本地)的URL看我博客有寫,這裡沒有全部給出,大家可以自己去試試看。 private String[] picture_uri = new String[] { "http://pic2.16pic.com/00/15/80/16pic_1580359_b.jpg", "http://pic.58pic.com/58pic/14/21/47/26t58PICywd_1024.jpg", "http://pic.58pic.com/58pic/14/21/42/15T58PICe3i_1024.jpg", "http://pic.58pic.com/58pic/14/21/44/52758PICtw2_1024.jpg", "http://pic.58pic.com/58pic/14/21/32/81U58PICJqm_1024.jpg", "http://pic.58pic.com/58pic/14/21/37/46B58PICudW_1024.jpg", "http://pic.58pic.com/58pic/14/21/39/72g58PICd3K_1024.jpg", "http://img15.3lian.com/2015/f3/08/d/02.jpg", "http://pic.58pic.com/58pic/14/21/47/99N58PICE7q_1024.jpg", "drawable://" + R.drawable.png_11 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 設置該Activity使用的布局文件 setContentView(R.layout.activity_main); // 獲取ListView控件 lsv_image_loader = (ListView) findViewById(R.id.lsv_image_loader); // 創建ImageLoaderBaseAdapter對象 ImageLoaderBaseAdapter adapter = new ImageLoaderBaseAdapter(this); // listView設置adapter lsv_image_loader.setAdapter(adapter); } /** * 自定義ImageLoaderBaseAdapter繼承BaseAdapter,重寫相關方法 * @author 鄒奇 * */ class ImageLoaderBaseAdapter extends BaseAdapter { private LayoutInflater inflater; public ImageLoaderBaseAdapter(Context context) { this.inflater = LayoutInflater.from(context); } @Override public int getCount() { return picture_uri.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return picture_uri[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder holder = null; if (convertView == null) { convertView = inflater.inflate(R.layout.lsv_item_image_loader, null); holder = new ViewHolder(); holder.iv_lin = (ImageView) convertView .findViewById(R.id.iv_lin); convertView.setTag(holder); } holder = (ViewHolder) convertView.getTag(); // 創建DisplayImageOptions對象並進行相關選項配置 DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_launcher)// 設置圖片下載期間顯示的圖片 .showImageForEmptyUri(R.drawable.ic_launcher)// 設置圖片Uri為空或是錯誤的時候顯示的圖片 .showImageOnFail(R.drawable.ic_launcher)// 設置圖片加載或解碼過程中發生錯誤顯示的圖片 .cacheInMemory(true)// 設置下載的圖片是否緩存在內存中 .cacheOnDisk(true)// 設置下載的圖片是否緩存在SD卡中 .displayer(new RoundedBitmapDisplayer(20))// 設置成圓角圖片 .build();// 創建DisplayImageOptions對象 // 使用ImageLoader加載圖片 imageLoader.displayImage(picture_uri[position], holder.iv_lin, options); return convertView; } /** * 控件緩存類 * @author 鄒奇 * */ class ViewHolder { ImageView iv_lin; } } @Override protected void onDestroy() { // 回收該頁面緩存在內存中的圖片 imageLoader.clearMemoryCache(); super.onDestroy(); } }

上面的代碼中我都給出了注釋,方便大家理解。這裡我給出的是網絡上的圖片的URL和drawable下的圖片的URL,比如上面的ImageLoaderBaseAdapter 裡,使用ImageLoader對象加載圖片的方法如下:

imageLoader.displayImage(picture_uri[position],holder.iv_lin, options);// ImageLoader對象利用圖片的URL加載圖片

其中displayImage方法的第一個參數是圖片的URL,第二個參數是ImageView控件。
一般來說,ImageLoader性能如果有問題,就和這裡的配置有關,尤其是ImageLoaderConfiguration。而這裡上面的一些配置代碼都是目前比較通用的,大家可以參考。


最後給大家講講ImageLoader的優化吧!這是我現在正在研讀的一本書上面提到的,這裡分享給大家。原文如下:

===========================================
盡管ImageLoader很強大,但一直把圖片緩存在內存中,會導致內存占用過高。雖然對圖片的引用是軟引用,軟引用在內存不夠的時候會被GC,但我們還是希望減少GC的次數,所以要經常手動清理ImageLoader中的緩存。
我們在上面MainActivity的 onDestroy()生命周期方法中,執行了ImageLoader的clearMemoryCache方法,以確保頁面銷毀時,把為了顯示這個頁面而增加的內存緩存清除。這樣,即使到了下個頁面要復用之前加載過的圖片,雖然內存中沒有了,根據ImageLoader的緩存策略,還是可以在本地磁盤上找到:

@Override
    protected void onDestroy() {
        // 回收該頁面緩存在內存中的圖片
        imageLoader.clearMemoryCache();
        super.onDestroy();
    }

這裡加載圖片時候,寫圖片的URL的時候需要注意,圖片的URL可以分為以下幾種:

// 網絡圖片
String imageUri = "http://pic2.16pic.com/00/15/80/16pic_1580359_b.jpg";   
//SD卡圖片
String imageUri = "file:///mnt/sdcard/zouqi.png"; 
// 媒體文件夾 
String imageUri = "content://media/external/audio/albumart/6";  
// assets 
String imageUri = "assets://zouqi.png";
//  drawable文件 
String imageUri = "drawable://" + R.drawable.zouqi;  

好了,所有的配置和方法都講完了。下面給大家演示一下加載的圖片效果:

listView的第一張圖片
這裡寫圖片描述


listView的第二張圖片
這裡寫圖片描述


listView的第三張圖片
這裡寫圖片描述


listView的最後一張圖片,最後的小狗圖片是drawable下的圖片資源
這裡寫圖片描述

這裡我寫的demo只加載了網絡的和drawable下的圖片,其他的圖片加載大家就自己去試試看,其實就是URL的寫法,這裡就不過多講了,上面有講到。最後大家別忘了給清單配置文件加網絡權限和寫權限:

    

 


每天進步一點點!加油!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved