Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android在ListView裡加載遠程圖片開發教程

Android在ListView裡加載遠程圖片開發教程

編輯:Android開發實例

ListView在Android應用裡扮演非常重要的角色,但很多開發者在使用ListView時都遇到過不少麻煩。一個常見的問題是:列表中要顯示一系列記錄,每條記錄帶有一張縮略圖(產品照片、用戶頭像等等),而這個縮略圖是通過一個遠程URL地址來標識的。這樣的應用場景該如何實現呢?

為了避免下載圖片帶來的延遲,所有遠程圖片都應該使用異步方式加載,即使用單獨的線程下載圖片,待圖片下載完畢後顯示在ImageView裡。Android裡可以像普通Java一樣啟動新線程,但當這個線程要更新界面時,必須使用Handler來請求,否則會為應用程序帶來潛在危害。

RemoteImageHelper

為了將復雜的邏輯分離,我們單獨寫一個名為RemoteImageHelper的類來處理“異步下載圖片並更新到界面”這個問題,這個類能夠實現以下功能:

  • 圖片開始下載前,ImageView裡顯示一個表示“正在加載”的占位圖;
  • 圖片在後台下載,下載完成後顯示在ImageView裡;
  • 若圖片下載失敗,ImageView顯示一個表示下載失敗的占位圖;

下面讓我們來看一下實現代碼:

首先需要有一個方法下載遠程圖片,這裡我們不用把圖片下載到手機上,直接返回一個InputStream類型的結果即可。如果運行時這個方法報錯,請檢查是否在AndroidManifest.xml裡添加了android.permission.INTERNET權限。

private InputStream download(String urlString) throws MalformedURLException, IOException {
    InputStream inputStream = (InputStream) new URL(urlString).getContent();
    return inputStream;
}

然後是最主要的異步加載圖片方法,“正在下載”和“下載失敗”的圖片可根據需要自己替換。代碼如下所示:

 
private final Map<String, Drawable> cache = new HashMap<String, Drawable>();

public void loadImage(final ImageView imageView, final String urlString, boolean useCache) {
    if (useCache && cache.containsKey(urlString)) {
        imageView.setImageDrawable(cache.get(urlString));
    }

    //Show a "Loading" image here
    imageView.setImageResource(R.drawable.image_indicator);

    Log.d(this.getClass().getSimpleName(), "Image url:" + urlString);

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            imageView.setImageDrawable((Drawable) message.obj);
        }
    };

    Runnable runnable = new Runnable() {
        public void run() {
            Drawable drawable = null;
            try {
                InputStream is = download(urlString);
                drawable = Drawable.createFromStream(is, "src");

                if (drawable != null) {
                    cache.put(urlString, drawable);
                }
            } catch (Exception e) {
                Log.e(this.getClass().getSimpleName(), "Image download failed", e);
                //Show a "download fail" image 
                drawable = imageView.getResources().getDrawable(R.drawable.image_fail);
            }
            
            //Notify UI thread to show this image using Handler
            Message msg = handler.obtainMessage(1, drawable);
            handler.sendMessage(msg);
        }
    };
    new Thread(runnable).start();
}
 

關於緩存:在這個例子裡我們使用一個內存中的HashMap作為圖片緩存,它實現簡單但當應用退出後緩存就會被清除。在實際項目裡,你可以考慮實現一個基於文件的緩存機制,即將下載的圖片保存到SD卡上,注意要定期清除長期不用的圖片以節約存儲空間。

使用RemoteImageHelper

如何使用這個類呢?下面是一個例子。請注意,為了達到更好的演示效果,代碼裡在調用loadImage()方法時第三個參數用false禁止了圖片緩存功能,在實際項目中,你很可能需要改為true來避免重復下載圖片以便提高性能。

 
List<MyRecord> exampleRecords;
LazyImageHelper lazyImageHelper = new LazyImageHelper();

class MyAdapter extends ArrayAdapter<MyRecord> {

    public MyAdapter(Context context) {
        super(context, R.layout.record_row, R.id.lblLabel, exampleRecords);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);
        MyRecord record = getItem(position);

        TextView lblLabel = (TextView) view.findViewById(R.id.lblLabel);
        ImageView imageView = (ImageView) view.findViewById(R.id.img);

        lblLabel.setText(record.getLabel());

        //For demo purpose, cache is DISABLED here.
        lazyImageHelper.loadImage(imageView, record.getImageUrl(), false);

        //To enable cache, simply use following code:
        //lazyImageHelper.loadImage(imageView, record.getImageUrl(), true);

        return view;
    }
}
 

以上代碼中的MyRecord是一個簡單的POJO類,表示一個業務對象,它具有id、label和imageUrl三個屬性。你可以在完整的工程代碼中找到它。

代碼下載

上述示例工程編譯後的APK文件點擊這裡下載,可運行在Android 2.1或以上版本。

上述示例工程的源代碼點擊這裡下載。

參考資料

Handler

android的消息處理機制

How do I do a lazy load of images in ListView

Issue 13959:Make listviews more programmer friendly

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