1

我有帶有EventAdapter的ListView。在ListView中的ImageViews不顯示

public class EventAdapter extends BaseAdapter { 
... 
public View getView(int position, View view, ViewGroup parent) { 
    ... 
    cache.imgIcon.setImageDrawable(ImgCache.setImg(url, progressBar)); 
    ... 
} 

ImgCache其緩存圖像的類。

public class ImgCache { 
    public static HashMap<String, Drawable> imgCache; 

    // get img from cache if exist, or download and put in cache 
    public static Drawable setImg(final String link, final ProgressBar progressBar) { 
     final Drawable[] image = {null}; 
     if (imgCache.containsKey(link)) { 
      image[0] = imgCache.get(link); 
      progressBar.setVisibility(View.INVISIBLE); 
     } else { 
      new AsyncTask<Void, Void, Drawable>() { 
       @Override 
       protected Drawable doInBackground(Void... params) { 
        URL url = null; 
        try { 
         url = new URL(link); 
         URLConnection connection = url.openConnection(); 
         image[0] = Drawable.createFromStream(connection.getInputStream(), "src"); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
        imgCache.put(link, image[0]); 
        return image[0]; 
       } 

       @Override 
       protected void onPostExecute(Drawable result) { 
        progressBar.setVisibility(View.INVISIBLE); 
       } 
      }.execute(); 
     } 
     return image[0]; 
    } 
} 

問題是什麼?

當我打開我的ActivityListView所有圖像開始加載。但加載完成後,他們不顯示。它看起來像:

enter image description here

然後我嘗試滾動2項,隨後返回到原來的位置。在這個操作之後,我可以看到2個帶有圖像的上層項目當我向他們滾動時,所有圖像也都可見。

enter image description here

+0

只是一個警告:'HashMap '取決於你有多少可繪圖和用戶正在使用的設備,你的應用程序會出現OutOfMemory錯誤。 – Budius

+0

無論如何,我可以獲得這個HashMap的大小嗎?什麼大小必須緩存? – Val

+0

緩存圖像(我通常使用位圖,但可繪製也一樣好)我建議你使用LruCache(https://developer.android.com/reference/android/support/v4/util/LruCache.html) – Budius

回答

2

根據您的問題,好像你需要刷新ListView圖像之後已被下載(因爲當你滾動,但會出現):

adapter.notifyDataSetChanged(); 
+0

我也考慮過這個問題,但是我必須在這裏指定這條線? – Val

+0

稱它onPostExecute – Carnal

1

的問題是,你的視圖加載並填充你的列表OnCreate,但那時你的異步任務還沒有返回你的列表,所以當getView調用你的緩存時它是空的,因爲當你再次調用android查看回收時調用getView,這次你的緩存有被填充。

我建議onPostExecute您在您的ListView適配器上調用NotifyDataSetChanged,一旦您擁有圖像,這將強制重繪。

2

AsyncTask是異步的所以您的應用程序的流程是:

ListView項需要顯示 - >通話Adapter.getView(...)的列表項 - >如果圖像不在緩存中,執行的AsyncTask並返回(不等待結果) 因此,當您向下滾動並備份時,將再次調用Adapter.get(...)方法,但是這次圖像在緩存中,因此它返回顯示的Drawable對象

解決此問題的一種方法是從AsyncTask回調適配器,它將在檢索到圖像後更新圖像,在適配器上調用notifyDataSetChanged,設置婷具體可繪製直接或類似的東西(顯示加載GIF在同時圖像?)

或者

調用的AsyncTask get(long timeout, TimeUnit unit)方法,將阻止該男子的線程和等待的AsyncTask完成。完成後,它會返回結果(在這種情況下,您的Drawable)。這會導致主UI線程在獲取圖像時掛起,因此不是最佳方式。