2011-11-07 38 views
1

我的工作,實現包含圖像的自定義ListView控件的應用程序。我能夠得到列表視圖下載和緩存圖像,但我想將下載到一個單獨的線程。要做到這一點,我創建了一個CachedLogoDownloader類誰的目標是異步下載圖像,並將它們保存在內存中通過自定義適配器類後訪問。Android的工作線程凍結主線程

的問題是,該線程保持了整個UI。即使run()中的代碼只是一個「thread.sleep()」,UI也會在發生徽標圖像請求時停止。同樣,在run()中放置一個無限循環導致程序無限期地掛起。

class CachedLogoDownloader{ 

private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>(); 
Context context; 
ArrayList<String> FIDs; 
Thread runner; 

public CachedLogoDownloader(Context inContext){ 
    this.context = inContext; 

    //list of company logos (by FID) to be downloaded 
    FIDs = new ArrayList<String>(); 

    //asynchronous downloader thread (single thread for lower-end devices. Shouldn't be much slower to get the images, though) 
    runner = new Thread(new Runnable() { 
     public void run() { 
      for(String FID:FIDs){ 
       Log.d(Cloud.DEBUG_TAG, "Icon Runnable for: " + FID); 
       Bitmap tempImage = Cloud.lookupIcon(context, FID); 
       cache.put(FID, tempImage); 
       FIDs.remove(FID);       
      } 

     } 
    }); 
} 

public Bitmap getLogo(Company aCompany){ 

    String currentFID = aCompany.getFID(); 

    //if the image has already been cached, return the cached image 
    if(cache.containsKey(currentFID)) 
    { 
     return cache.get(currentFID); 
    } 
    else 
    { 
     //add the logo to the list of logos to be downloaded     
     FIDs.add(currentFID); 

     //if the downloader thread completed (or hasn't started yet) make it download stuff. 
     if(!runner.isAlive()){ 
      runner.setPriority(Thread.MIN_PRIORITY); 
      runner.run(); 
     } 

     //return null for now (until next time, whent the image will be in the cache!.) 
     return null; 
    } 



} 

}

+2

相反runner.run的(),你應該使用runner.start(),否則你的線程的run()方法實際執行在同一個線程。 – slkorolev

回答

2

runner.run();

這不是啓動一個單獨的線程,而只是在調用線程上執行run方法的內容。你可能想

runner.start();

此外,如果(!runner.isAlive()){

這種檢查可能不是非常有用的,你不能啓動一個線程不止一次,所以

。當你需要圖像時(或者當你啓動應用程序時)啓動線程,然後等待它完成它的工作。如果你需要更復雜的邏輯,比如線程池或錯誤處理,你應該使用一個庫來進行異步映像加載。