2014-08-27 83 views
0

我正在使用ListView的自定義數據適配器,它列出了我的應用程序中的一些類別。當我添加一個新的類別或滾動ListView每個項目混合,不知何故它不會爲新添加的數據創建一個新的項目。這是我的自定義適配器的代碼;Android DataAdapter混合數據值

public class CategoryAdapter extends BaseAdapter { 

List<Category> mList; 
Context mContext; 

public CategoryAdapter(Context context, List<Category> data) { 
    mList = data; 
    mContext = context; 
} 

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

@Override 
public Object getItem(int position) { 
    if (position < 0 || position >= mList.size()) 
     return null; 
    return mList.get(position); 
} 

@Override 
public long getItemId(int position) { 
    if (position < 0 || position >= mList.size()) 
     return -1; 
    return mList.get(position).getId(); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    CategoryDelegate del; 
    if (convertView == null) { 
     System.out.println("CV Null pos: " + position); 
     del = new CategoryDelegate(mContext, mList.get(position)); 
     int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics()); 
     del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height)); 
    } else { 
     System.out.println("CV EXIST pos: " + position + "/" + mList.get(position).getTitle() + " =? " + ((CategoryDelegate) convertView).getCategory().getTitle()); 
     del = (CategoryDelegate) convertView; 
    } 
    return del; 
} 

public void setData(List<Category> data) { 
    mList = data; 
    notifyDataSetChanged(); 
} 

public class CategoryDelegate extends LinearLayout { 
    private TextView mTitle; 
    private TextView mCount; 
    private Category mCategory; 

    public CategoryDelegate(Context context, Category category) { 
     super(context); 
     mCategory = category; 

     Resources res = getResources(); 

     //leftMargin = 11dp; textAlignVCenter; fontSize = 20dp(sp!); color = Color.rgb(149, 155, 171); 
     mTitle = new TextView(context); 
     mTitle.setTextColor(Color.rgb(149, 155, 171)); 
     mTitle.setGravity(Gravity.CENTER_VERTICAL); 
     mTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); 
     mTitle.setText(category.getTitle()); 
     LayoutParams titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 
     titleParams.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 11, res.getDisplayMetrics()); 
     titleParams.weight = 1; 
     mTitle.setLayoutParams(titleParams); 
     addView(mTitle); 

     //rightMargin = 10dp; textAlignVCenter; fontSize = 15dp(sp!); color = Color.rgb(149, 155, 171); 
     mCount = new TextView(context); 
     mCount.setTextColor(Color.rgb(149, 155, 171)); 
     mCount.setGravity(Gravity.CENTER_VERTICAL); 
     mCount.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); 
     mCount.setText(String.valueOf(category.getSize())); 
     LayoutParams countParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 
     countParams.gravity = Gravity.RIGHT; 
     countParams.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 13, res.getDisplayMetrics()); 
     mCount.setLayoutParams(countParams); 
     addView(mCount); 
    } 

    public Category getCategory() { 
     return mCategory; 
    } 
} 

當我添加一個新的類別或向下滾動到列表中,在getView if (convertView == null) {從來沒有工作,我不知道爲什麼,而是去現有convertView和所有數據點之後混合起來。任何想法如何可以使這個適配器工作?

回答

0

如果我更改getView函數就像;

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    CategoryDelegate del; 
    if (convertView == null) { 
     del = new CategoryDelegate(mContext, mList.get(position)); 
     int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics()); 
     del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height)); 
    } else { 
     if (((CategoryDelegate) convertView).getId() != mList.get(position).getId()) { 
      del = new CategoryDelegate(mContext, mList.get(position)); 
      int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics()); 
      del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height)); 
     } else { 
      del = (CategoryDelegate) convertView; 
     } 
    } 
    return del; 
} 

的ListView工作正常,但我不知道如果我做的東西好還是壞。有沒有人可以解釋我發生了什麼事。有沒有機會讓我內存泄漏?

編輯:正如我擔心內存泄漏,上面的代碼正是造成內存泄露,讓我發現了大約觀點持有者模式值得好好讀條http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/

然後,我改變了我的代碼;

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    CategoryDelegate del; 
    if (convertView == null) { 
     del = new CategoryDelegate(mContext, mList.get(position)); 
     int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics()); 
     del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height)); 
    } else { 
     if (((CategoryDelegate) convertView).getId() != mList.get(position).getId()) { 
      ((CategoryDelegate) convertView).updateDelegate(mList.get(position)); 
     } 
     del = (CategoryDelegate) convertView; 
    } 
    return del; 
} 

最後CategoryDe​​legate像;

 public void updateDelegate(Category category) { 
     mTitle.setText(category.getTitle()); 
     mCount.setText(String.valueOf(category.getSize())); 
     mCategory = category; 
    } 

一切就像一個魅力現在...

0

convertView != null,你需要一個新的mList.get(位置)值來更新德爾和更新任何視圖的使用該值。適配器將回收視圖以避免重新實例化全新視圖。所以當你收到一個非null的convertView時,你正在接收一個循環視圖。這意味着您需要使用該職位的任何新數據更新該視圖。請注意,回收視圖並不意味着它使用相同的位置。它可能來自一個完全不同的位置使用的視圖。

另外,我應該注意,你創建視圖的方式並不是一個乾淨或推薦的方式。更好的方法是創建一個單獨的獨立類CategoryDe​​legate,然後直接在XML文件中使用該類。在那裏定義所有屬性並誇大該視圖。

ya的進一步閱讀:How GetView Works