2016-03-31 42 views
0

我在我的可滾動列表視圖中出現一些奇怪的行爲。它由BaseAdapter控制。ListView BaseAdapter掛

當我向上或向下滾動時,它有時會掛起,然後向相反的方向反彈。我不知道爲什麼,也不知道如何排除故障。

我的底座適配器在下面,它加載了大約90個帶有圖像和一堆文本的片段。

public class PosterListAdapter extends BaseAdapter { 

     private final ArrayList<Poster> listItems; 

     private final LayoutInflater inflater; 

     public PosterListAdapter(ArrayList<Poster> listItems, LayoutInflater inflater) { 
      this.listItems = listItems; 
      this.categoryList = categoryItems; 
      this.inflater = inflater; 
     }  


     @Override 
     public int getCount() { 
      //Log.d("getCount", String.valueOf(this.listItems.size())); 
      return this.listItems.size();    
     } 

     @Override 
     public Poster getItem(int i) { 

      return this.listItems.get(i); 
     } 

     @Override 
     public long getItemId(int i) { 
      return 0; 
     } 

     @Override 
     public View getView(int i, View convertView, ViewGroup viewGroup) { 
      MyViewHolder mViewHolder; 
      SparseArray<String> categoryMap = db.getCategoryMap(); 

      if (convertView == null) { 
       convertView = inflater.inflate(R.layout.catalog_list_fragment, viewGroup, false); 
       mViewHolder = new MyViewHolder(convertView); 
       convertView.setTag(mViewHolder); 
      } else { 
       mViewHolder = (MyViewHolder) convertView.getTag(); 
      } 

      //LayoutParams params = (LayoutParams) imageView.getLayoutParams(); 

      Poster item = this.listItems.get(i); 

      String filename = item.getPosterFilename(); 

      mViewHolder.posterAuthor.setText("Author: "+item.getPresenterFname()+' '+item.getPresenterLname()); 
      mViewHolder.posterAltAuthors.setText("Supporting Authors: "+item.getPosterAuthors()); 
      mViewHolder.posterTitle.setText(item.getPosterTitle()); 
      mViewHolder.posterSynopsis.setText(item.getPosterSynopsis()); 
      mViewHolder.posterNumber.setText("Poster: "+String.valueOf(item.getPosterNumber())); 
      mViewHolder.posterPresentation.setText("Live Presentation: "+item.getSessionDate()+" at "+item.getSessionTime()+"\nAt Station: "+item.getPosterStation());   

      String category = categoryMap.get(item.getCatID()); 

      mViewHolder.posterCategory.setText("Category: "+category); 

      File imgFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(), "/"+filename+"/"+filename+".png"); 

//Here I thought maybe the resizing of the image or even the image itself 
// was causing the hang up so I tried the list without it and it is still 
// hanging. 
      //mViewHolder.imageView.setImageURI(Uri.fromFile(new File(imgFile.toString()))); 
      if (imgFile.exists()){ 
       /*Bitmap bmp = BitmapFactory.decodeFile(imgFile.toString()); 
       int newWidth = 500; 
       Bitmap sizedBMP = getResizedBitmap(bmp, newWidth); 

       mViewHolder.imageView.setImageBitmap(sizedBMP);*/ 
      } 
      else{ 
       //set no image available 
      } 

      return convertView; 
     } 

     private class MyViewHolder { 

      TextView posterTitle, posterAuthor, posterSynopsis, posterCategory, posterNumber, posterAltAuthors,posterPresentation; 
      ImageView imageView; 

      public MyViewHolder(View item) { 
       posterTitle = (TextView) item.findViewById(R.id.poster_title); 
       posterAuthor = (TextView) item.findViewById(R.id.poster_author); 
       posterAltAuthors = (TextView) item.findViewById(R.id.poster_altAuthors); 
       posterSynopsis = (TextView) item.findViewById(R.id.poster_synopsis); 
       posterCategory = (TextView) item.findViewById(R.id.poster_category); 
       posterNumber = (TextView) item.findViewById(R.id.poster_number); 
       posterPresentation = (TextView) item.findViewById(R.id.poster_presentation); 

       imageView = (ImageView) item.findViewById(R.id.poster_thumb); 
      } 
     } 
    } 

我知道這是一個代碼大塊,它可能是醜陋的。如果你能在正確的方向指向我,如何麻煩拍攝,這將是有益的,以及它。我正在使用eclipse。

回答

1

我敢打賭,如果您將該行File imgFile = new File(...(以及取決於imgFile的代碼)註釋爲您的列表滾動功能將會改進。

這仍然是I/O操作,因爲getView()在UI線程中運行,所以可能會導致打嗝。

你應該做的是:一旦你在getView()ImageView,啓動一個AsyncTask打開文件,對其進行解碼,並指定位圖到ImageView

然後你必須處理這樣的事情:ImageView得到回收,但任務沒有完成。

閱讀本文:Multithreading for Performance | Android Developers Blog。它處理來自遠程服務器的圖像,但所有原則仍然相同。

另請參見:是否該行SparseArray<String> categoryMap = db.getCategoryMap();做數據庫查找?這也可能導致呃逆。

TL; DR getView()需要快;在非UI線程中放慢操作。

+0

謝謝你的建議。我現在正在努力實施它們。 categoryMap是一個數據庫調用,所以我把它移到了BaseAdapter之外。當我關閉imageView時,我注意到了一個改進。每隔一段時間仍然會有一個「反彈」,但也許這就是Android UI造成的。 – silversunhunter

0

我同意以前的答案,看起來像創建新的File是唯一沉重的操作掛起你的應用程序。

嘗試使用一些圖片加載庫,例如,Glide。它會簡化你的代碼,你也不必處理後臺工作。圖書館會爲你做這一切。

1.導入庫例如如果你使用gradle這個插入到這一點您build.gradle文件:

repositories { 
    mavenCentral() // jcenter() works as well because it pulls from Maven Central 
} 

dependencies { 
    compile 'com.github.bumptech.glide:glide:3.7.0' 
    compile 'com.android.support:support-v4:19.1.0' 
} 

2.In適配器更換與加載圖片與此代碼:

Glide 
    .with(context) 
    .load(<full path to your local file>) 
    .into(mViewHolder.imageView); 

3.And它是所有。 Glide將在內部處理回收和其他事情,同時它也針對快速加載和平滑滾動進行了優化。

0

圖像相關的流程真的在應用程序的UIThread上消耗太多內存,您應該使用異步(背景)方法設置圖像。或者,如果對你來說很麻煩,那麼有很多可用的庫可以做到這一點。我特別推薦使用Picasso,因爲它非常動態,易於使用並且定期更新。載入圖像需要一行代碼:

Picasso.with(getApplicationContext()).load(<your image path or url or resource id>).into(YourImageView); 

畢加索也有多種圖像選項供您選擇。

1

數據庫相關操作應該在單獨的線程中完成。因爲如果記錄數量更大,則可能需要時間來獲取數據。

和getView()方法將被多次調用。我們可以說它將被循環調用,直到數組列表的大小(getCount())。

第二件事:文件操作也應該在單獨的線程中完成。因爲IO任務也有些時候耗時。

解決方案:

SparseArray<String> categoryMap = db.getCategoryMap(); 將這個線路輸出getView()方法作爲我看不到在此行中的任何列表相關的參數。這應該在構造函數分開的線程完成。

運行數據庫的操作和在單獨的線程文件IO喜歡使用的AsyncTask