1. 程式人生 > >Android中使用ImageLoader載入圖片

Android中使用ImageLoader載入圖片

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

  • 這時就是ImageLoader的 show time
    了。ImageLoader的目的是為了實現非同步的網路圖片載入、快取及顯示,支援多執行緒非同步載入。

  • 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物件。程式碼如下所示:

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的寫法,這裡就不過多講了,上面有講到。最後大家別忘了給清單配置檔案加網路許可權和寫許可權:
<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

ImageLoader的jar包資源:點我下載

載入圖片的Demo:點我下載

每天進步一點點!加油!

相關推薦

Android使用ImageLoader載入圖片

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

AndroidWebView載入Html圖片新增點選事件

    基本的思路: (1)WebView來載入HTML。 (2)向HTML中注入JavaScript,利用JavaScript來呼叫Android中的方法(執行一些跳轉的操作等等)。  首先你必須有一個HTML或者是一個地址,或者是存到本地的一個檔案。我這裡使用的是存到本

Android 通過RGB_565載入圖片在記憶體佔用大小

我有一張 420*210 的png圖片,放在assets 目錄下。通過如下方式載入到記憶體中: BitmapFactory.Options options =new BitmapFactory.Options(); options.inPreferredConfig = B

在列表ImageLoader載入圖片可以通過此方法讓其延遲載入

ListView來顯示大量的圖片,而當我們快速滑動GridView,ListView,我們希望能停止圖片的載入,而在GridView,ListView停止滑動的時候載入當前介面的圖片ImageLoad

android開發ImageLoader網路圖片載入簡單使用

     Android上最讓人頭疼的莫過於從網路獲取圖片、顯示、回收,任何一個環節有問題都可能直接OOM,這個專案或許能幫到你。Universal Image Loader for Android的目的是為了實現非同步的網路圖片載入、快取及顯示,支援多執行緒非同步載入。它最

Android處理大圖片圖片壓縮

oca 內存空間 pan std ret bitmap sans source tar 1、BitmapFactory.Options中的屬性 在進行圖片壓縮時,是通過設置BitmapFactory.Options的一些值來改變圖片的屬性的,以下我們來看看BitmapF

android畫圓形圖片的幾種辦法

http hub image art 鋸齒 tar ets oid tex 在開發中常常會有一些需求,比方顯示頭像,顯示一些特殊的需求,將圖片顯示成圓角或者圓形或者其它的一些形狀。可是往往我們手上的圖片或者從server獲取到的圖片都是方形的。這時候就須要我們自

AndroidViewPager載入空白

記錄一個bug 現象: viewpager載入空白 我的佈局是MainActivity裡面主頁面是5個fragment,然後在MainActivity裡面還有一個側邊欄DrawLayout,其中我想在DrawLayout的佈局中是一個Tablayout+ViewPager+Fragm

ImageLoader載入圖片

ImageLoader載入圖片 1主佈局 <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android=“http://sche

ImageLoader載入圖片

1.建立一個App繼承Application(APP的頁面) //優先於所有頁面(Activity)建立 //主要負責應用全域性初始化 //該物件也是一個context public class App extends Application { @Override public

Android一張圖片佔據的記憶體大小是如何計算

最近封裝了個高斯模糊元件,正好將圖片相關的理論基礎也梳理了下,所以,這次就來講講,在 Android 中,怎麼計算一張圖片在記憶體中佔據的大小,如果要優化,可以從哪些方向著手。 提問 閱讀本篇之前,先來想一些問題: Q1:一張 png 格式的圖片,圖片檔案大小為 55.8KB,那麼它載入進記憶體時所佔的大小是

【轉】QmlImage載入圖片再不同平臺的方式

今天用QML中Image載入win系統下的本地路徑圖片的時候, 發現無論加絕對路徑或file://+path都打不開,就很奇怪,經過一番 查閱發現,各個系統的載入方式都不相同, win系統:     Image {             id:  preview

Android 資原始檔圖片轉 Bitmap 和 Drawable 以及相互轉換的方法

Android 圖片轉換的方法總結: 一、Bitmap 轉換成 Drawable 對 Bitmap 進行強制轉換 Drawable drawable = new BitmapDrawable(bmp); 二、Drawable 轉換成 Bitmap 方法一 通過 BitmapFa

webView--AndroidwebView載入H5時,H5頁面在不同的手機可能出現文字或者圖示類似換行的現象

@Override  public Resources getResources() { Resources res = super.getResources(); Configuration config=new Configuration(); config.setToDefaults(); res.up

列表Glide載入圖片大小顯示不正常問題

Glide載入圖片時大時小 前言:最近在專案中發現了一個奇怪的現象,在列表的item佈局中使用了glide來載入網路圖片,奇怪的現象出現了…同一張圖,同一份資料,有的時候顯示正常,有的時候該圖片顯示出來會稍微小一圈… 解決辦法:百思不得其解,找了很多資料,以為對recyclervie

Android 關於載入Bitmap知識點

 在安卓開發中遇到載入圖片是很平常的事情,圖片即bitmap,但是Android對於每一個應用程式只分配了16M的記憶體空間,所以在載入比較大點的bitmap的時候很容易,會出現OOM異常。 android 中載入圖片的類BitmapFactary,提供了四類方法:decodeS

android動態載入webview,webview載入html資料,並且隱藏滾動條

 ScrollView layouts = (ScrollView) findViewById(R.id.web); WebView webviews = new WebView(DtDetailActivity.this);webviews.setVisibility(

Android如何編寫圖片選擇器,實現按點選按鈕時按鈕的圖片或者顏色發生變化

1. 先看個圖,展示下我們要實現的效果:,點選按鈕的時候,按鈕變為這種顯示效果。 2. 其實這就是個圖片選擇器的編寫,當按鈕點選的時候,用另一張圖片去替換原有圖片,實現顏色的變化。 3. 具體步驟:     (1)首先在應用程式下→res目錄下建立一個folder,命名為d

Android為網路圖片設定高斯模糊效果

寫一個方法,用來對Bitmap進行高斯模糊: public static Bitmap blurBitmap(Bitmap bitmap ,Context context){ //Let

android 使用Glide載入圖片閃動問題

1、RecyclerView 有自己預設的動畫,去除預設動畫 ((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); 並且設定對應的adapter,