2012-01-04 63 views
3

當我滾動它時,我的listview重新排序。這很混亂。爲什麼當我滾動瀏覽時,我的listview重新排序?

下面是我使用的自定義適配器:

public class LoadExpenseList extends BaseAdapter{ 
     List<Expense> expenses; 
     Context context; 

     public LoadExpenseList(Context context, int textViewResourceId, 
       List<Expense> expenses) { 
      super(); 
      this.expenses = expenses; 
      this.context = context; 
     } 

     public View getView(final int position, View convertView, ViewGroup parent){ 
      //View v = convertView; 
      AvailableExpenseView btv; 

      if (convertView == null) { 
       btv = new AvailableExpenseView(context, expenses.get(position)); 
      } else { 
       btv = (AvailableExpenseView) convertView; 
      }   
      btv.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        Log.i("Expense_Availables", "Item Selected!!"); 
        Intent intent = new Intent(getActivity(), ItemDetailActivity.class); 

        int id = expenses.get(position).getExpenseItemId(); 
        intent.putExtra("id", id); 

        startActivity(intent); 
       } 

      }); 

      btv.setOnLongClickListener(new OnLongClickListener() { 

       @Override 
       public boolean onLongClick(View arg0) { 
        // TODO Auto-generated method stub 
        return false; 
       } 

      }); 

      registerForContextMenu(btv); 

      return btv; 
     } 

     @Override 
     public int getCount() { 
      return expenses.size(); 
     } 

     @Override 
     public Object getItem(int position) { 
      return expenses.get(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      return expenses.get(position).getExpenseItemId(); 
     } 

    } 

回答

4

因爲你的觀點(AvailableExpenseView)與項目建設,那麼當適配器試圖通過convertView重用的意見,你會得到一個觀點,即已經綁定到另一個項目。

不要用您的模型項目構建視圖,而應調用類似convertView.setExpense(expenses.get(position))的東西。

ListView將嘗試重用視圖來提高性能。因此,會發生什麼情況是,列表中的第一個項目將與新創建的視圖一起顯示,隨後在您滾動時它將嘗試重新使用以前創建的視圖,爲您提供通過convertView的視圖。注意這些行:

 if (convertView == null) { 
      // You create a view using the proper item 
      btv = new AvailableExpenseView(context, expenses.get(position)); 
     } else { 
      // You don't override the item that was previously assigned 
      // when the view was created 
      btv = (AvailableExpenseView) convertView; 
     }  

如果convertView爲空要創建一個新的觀點,但你有一個項目構建您的視圖。所以我們假設這個被調用的位置爲0.您使用列表中的第一個開銷創建一個視圖。之後,listView想要讓視圖位置爲20,並且說「ok讓我們重用我們用於位置0的視圖」,因此它將此視圖作爲convertView傳遞,但是此視圖已經在位置0上創建了該視圖而且你不會覆蓋這個。所以,你最終使用了第一個項目來表示第20項的視圖。

爲了解決這個問題,你可以很容易地做這樣的事情:

 AvailableExpenseView btv; 

     if (convertView == null) { 
      // dont create your view with an item 
      btv = new AvailableExpenseView(context); 
     } else { 
      btv = (AvailableExpenseView) convertView; 
     } 

     // Assign the expense wether it is a newly created view or 
     // a view that is reused 
     btv.setExpense(expenses.get(position)); 

當然,你必須編輯AvailableExpenseView並創建一個setExpense()方法來填充你的看法。

+0

你能解釋一下你的意思嗎?我不太清楚你的意思。 – Cody 2012-01-04 18:00:23

+0

當然不適合編輯我的答案。 – aromero 2012-01-04 18:06:00

0

您應該設置費用爲expense.get(position)for recycled AvailableExpenseView以及您爲新實例執行此操作。

當實例被回收,只是在錯誤的行(他們在那裏立即行,而不是你重用它們的行)顯示錯誤的代價。

更確切地說,你不給你的代碼爲AvailableExpenseView,但它可能looke像

 public class AvailableExpenseView { 

      private Expense expense = null; 

      public class AvailableExpenseView(Context context) { 
      super(context); 
      }//cons 

      /* 
      Just add this method and use it. 
      */ 

      public void setExpense(Expense expense) { 
      this.expense = expense; 
      }//met 
     }//class 

然後,在適配器中做到這一點:

 if (convertView == null) { 
      btv = new AvailableExpenseView(context); 
     } 
     btv = (AvailableExpenseView) convertView; 
     btv.setExpense(expenses.get(expenses.get(position))); 

它的好,有分量與一個鬆散的構造函數。想想JVM裏面的例子,不需要任何東西來創建一個按鈕。然後,您可以通過正交方法自定義屬性的「setter」。以這種方式設計您的組件,使它們易於使用,並且更具多價性。

0

你的問題是在這裏:

if (convertView == null) { 
    btv = new AvailableExpenseView(context, expenses.get(position)); 
} else { 
    btv = (AvailableExpenseView) convertView; 
} 

如果convertView爲空,那麼你會創建一個新的AvailableExpenseView在位置的費用。這可以。

但是,如果convertView不爲空,那麼您將引用現有的AvailableExpenseView。這在之前已經被初始化(在前一種情況下)爲與您想要在當前位置顯示的費用不同的費用。

你有兩個選擇:設置BTV費用後這個if塊,所以正確的費用是用來無論你正在創建一個新的AvailableExpenseView或回收的一個 -

或:在else塊,爲回收視圖設置正確的費用對象。

相關問題