<button id="u2w23"></button>

<tbody id="u2w23"><track id="u2w23"></track></tbody><dd id="u2w23"><track id="u2w23"></track></dd><button id="u2w23"><acronym id="u2w23"></acronym></button> <tbody id="u2w23"><noscript id="u2w23"></noscript></tbody>

  • <button id="u2w23"></button><li id="u2w23"><acronym id="u2w23"><cite id="u2w23"></cite></acronym></li>

  • 如何在ListView里加載遠程圖片?

    [來源] 達內    [編輯] 達內   [時間]2012-11-12

    ListView在Android應用里扮演非常重要的角色,但很多開發者在使用ListView時都遇到過不少麻煩

    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三個屬性。你可以在完整的工程代碼中找到它。

    資源下載

    ?