2014-09-05 58 views
0

我試圖做一個列表視圖,其中包含每一行中的視圖。該視圖包含2個textview和1個gridview,它是2列。在每一列中,我都使用由2個文本視圖組成的基本佈局。如何解決內存泄漏gridview到列表視圖? - Android

這是在gridview的每個塊中使用的基本佈局預覽。

enter image description here

下面是它的XML; - 第一視圖 -

<?xml version="1.0" encoding="utf-8"?> 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:id="@+id/listview_item"> 

<TextView 
    android:layout_width="220dp" 
    android:layout_height="wrap_content" 
    android:textSize="18dp" 
    android:text="Item Name" 
    android:id="@+id/list_item" 
    android:maxLines="1" 
    android:layout_marginLeft="5dp" 
    /> 

<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Price" 
    android:textSize="18dp" 
    android:id="@+id/item_price" 
    android:layout_alignParentRight="true" 
    android:layout_alignParentEnd="true" 
    android:layout_marginRight="5dp"/> 

</RelativeLayout> 

這是我的第二個視圖,其中包含2個textview和1個gridview。

enter image description here

這裏對XML的; - 第二視圖 -

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:id="@+id/listview_item" 
android:orientation="vertical"> 

<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textSize="40dp" 
    android:text="Kategori" 
    android:id="@+id/categories_title_list_layout"/> 

<GridView 
    android:layout_width="match_parent" 
    android:layout_height="0dp" 
    android:id="@+id/gridView_list_layout" 
    android:numColumns="2" 
    android:layout_weight="1"/> 

<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Not: Lorem ipsum dolor sit amet.." 
    android:textSize="18dp" 
    android:id="@+id/categories_note"/> 

</LinearLayout> 

這是我最後的看法; - 第三視圖 -

enter image description here

這ListView的每一行,把我的第二個觀點的形狀採用第一種觀點的形狀。

這是我創建這個視圖的適配器。 對於第一視圖我使用這個適配器;

public class ItemListAdapter extends BaseAdapter { 

private Context context; 
private ArrayList<Item> items; 

public ItemListAdapter(Context context, ArrayList<Item> items) { 
    super(); 
    this.context = context; 
    this.items = items; 
} 

public int getCount() { 
    return items.size(); 
} 

public Object getItem(int i) { 
    return items.get(i); 
} 

public long getItemId(int i) { 
    return i; 
} 

public View getView(final int i, View view, ViewGroup viewGroup) { 
    ViewHolder holder; 

    if(view == null) { 
     holder = new ViewHolder(); 
     LayoutInflater inflater = (LayoutInflater)  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = inflater.inflate(R.layout.listview_item_content, null); 

     holder.title = (TextView) view.findViewById(R.id.list_item); 
     holder.price = (TextView) view.findViewById(R.id.item_price); 

     view.setTag(holder); 
    } 

    holder = (ViewHolder) view.getTag(); 
    Typeface face=Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf"); 
    holder.title.setTypeface(face, Typeface.BOLD); 
    holder.title.setText(items.get(i).getName()); 
    holder.title.setTextColor(Color.parseColor(Shop.getInstance().getItemGridTextColor())); 
    holder.price.setText(Global.getLocalizedPriceStringByLocale(Shop.getLocale(), items.get(i).getPrice())); 
    holder.price.setTextColor(Color.parseColor(Shop.getInstance().getItemGridTextColor())); 

    return view; 
} 

public class ViewHolder { 
    public TextView title; 
    public TextView price; 
} 
} 

(此適配器需要項目的名稱和價格,並把它們放入第一個視圖。)

我這創建第二個視圖第二適配器就在這裏;

public class CategoryListAdapter extends BaseAdapter { 

private Context context; 
//private ArrayList<Item> items; 
private ArrayList<Category> currentCategory; 

public CategoryListAdapter(Context context, ArrayList<Category> category) { 
    super(); 
    this.context = context; 
    currentCategory = category; 

} 

public int getCount() { 
    return currentCategory.size(); 
} 

public Object getItem(int i) { 
    return currentCategory.get(i); 
} 

public long getItemId(int i) { 
    return i; 
} 

public View getView(final int i, View view, ViewGroup viewGroup) { 

    ViewHolder holder; 

    if (view == null) { 
     holder = new ViewHolder(); 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = inflater.inflate(R.layout.grid_list_layout, null); 

     holder.title = (TextView) view.findViewById(R.id.categories_title_list_layout); 
     holder.gridView = (GridView) view.findViewById(R.id.gridView_list_layout); 
     holder.note = (TextView) view.findViewById(R.id.categories_note); 

     view.setTag(holder); 
    } 

    holder = (ViewHolder) view.getTag(); 
    Typeface face = Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf"); 
    holder.title.setTypeface(face, Typeface.BOLD); 

    if(currentCategory.get(i).getName().equals("")){ 
     holder.title.setText("Diğer"); 
    }else{ 
     holder.title.setText(currentCategory.get(i).getName()); 
    } 

    holder.title.setTextColor(Color.parseColor(Shop.getInstance().getItemGridTextColor())); 
    holder.note.setText(currentCategory.get(i).getDeepNote()); 
    holder.note.setTextColor(Color.parseColor(Shop.getInstance().getItemGridTextColor())); 
    holder.gridView.setAdapter(new ItemListAdapter(context, currentCategory.get(i).getItems())); 
    holder.gridView.setBackgroundColor(Color.parseColor(Shop.getInstance().getItemGridBackgroundColor())); 
    holder.gridView.getBackground().setAlpha(180); 

    return view; 
} 

public class ViewHolder { 
    public TextView title; 
    public GridView gridView; 
    public TextView note; 
} 
} 

我用這個適配器來創建ListView。

這是我的問題。這工作真的很慢。我的意思是ListView凍結了片刻,然後滑下來,當我嘗試向下移動。 還有一個關於GridView高度的問題。我的GridView的高度是wrap_content,但它的行爲不像wrap_content。它顯示更大或更小的GridView。

enter image description here

例如;在「Diğer」標題下,應該有一個GridView,它只包含1個項目,正如你所看到的,但它不能顯示完整的文本。在「AdetÜrünler」下,應該有190個項目,但它只能查看其中的20個。

這些是我的問題。對不起,我的編碼。如果你不明白我的代碼,請問我。 感謝您的幫助。

回答

1

這個答案不會給你一個明確的解決方案,不是因爲我不願意,而是因爲它是不可能的(甚至更難,而不僅僅是查看你的代碼,但非常瞭解它)。但根據我的經驗,我可以告訴你,那些內存泄漏不僅僅是由於直接引用的對象 - 你聲明的對象(並且繼續引用另一個類/對象)依賴於許多其他類等等,而且可能您看到內存泄漏是由於您的任何實例的不正確處理,而這些實例同時引用了其他實例。

調試內存泄漏通常是一項非常艱苦的工作,不僅因爲如上所述,它有時不直接依賴於您聲明的內容,而且因爲找到解決方案可能不是微不足道的。你可以做的最好的事情就是你已經做的事情:DDMS + HPROF。我不知道你有多少知識,但儘管這不是一種通用方法,但this link幫助我在代碼中找到內存泄漏。

雖然看起來微不足道,但調試這些類型的最好方法是逐步刪除部分代碼(總體來說,暗示與其他類的實例一起工作)並查看HPROF報告如何更改。

0

據我理解您的問題,它的滾動你的截圖已經顯示的列表中低性能?

你的問題的解決方案將需要重新編寫適配器和佈局。你的性能問題是由於你使用了相當大的列表項(例如一個列表項中包含190個項目的網格),在滾動列表期間必須加載,以及列表項的可重用性很低。

另外,我不喜歡使用視圖持有者。

要擺脫網格,您可以使用包含'標題','筆記'和其間的單個網格行的對象列表(或如下所示的包裝)。您將不得不覆蓋一些適配器方法,以在一個列表視圖中使用多個視圖類型(如下所示)。也許你還需要更多的代碼來將你的模型映射到新的列表中,但畢竟,你的表現應該恢復正常。

唯一的缺點我知道(並沒有快速解決方案)是由於單個列表項中的高度不同,整個列表的滾動條有時會​​顯示一種奇怪的行爲(如:滾動條期間滾動條指示器的高度發生變化)

包裝

public class ListItemWrapper { 
    ListItemType type; 
    Object content; 

    public ListItemWrapper(ListItemType type, Object content) { 
     this.type = type; 
     this.content = content; 
    } 

    public enum ListItemType { Title,Note, Content;} 
} 

ListAdapter

public class ListAdapter extends ArrayAdapter<ListItemWrapper> { 

    private LayoutInflater inflater; 

    public ListAdapter(Context context, int resource) { 
     super(context, resource); 
     inflater = LayoutInflater.from(context); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ListItemWrapper item = getItem(position); 
     switch (item.type) { 
      case Content: return getViewForGridRow((GridRowContent)item.content, convertView); 
      case Note: return getViewForNote((String)item.content, convertView); 
      case Title: return getViewForTitle((String) item.content, convertView); 

     } 
     return convertView; //this case should never happen 
    } 

    private View getViewForTitle(String content, View convertView) { 
     if (convertView == null) { 
      //TODO inflate a new view for the title 
      convertView = inflater.inflate(R.layout.titleRowLayout, null); 
     } 
     //TODO set textview value for the title 
     return convertView; 
    } 

    private View getViewForNote(String content, View convertView) { 
     if (convertView == null) { 
      //TODO inflate a new view for the note 
      convertView = inflater.inflate(R.layout.noteRowLayout, null); 
     } 
     //TODO set textview value for the note 
     return convertView; 
    } 

    private View getViewForGridRow(GridRowContent item, View convertView) { 
     if (convertView == null) { 
      //TODO inflate a new view for a single grid row 
      convertView = inflater.inflate(R.layout.gridRowLayout, null); 
     } 
     //TODO set values of the grid row (e.g. textview items) 
     return convertView; 
    } 

    @Override 
    public int getItemViewType(int position) { 
     return getItem(position).type.ordinal(); 
    } 

    @Override 
    public int getViewTypeCount() { 
     return ListItemType.values().length; 
    } 
} 

我簡化了一部分模型,但我希望你能明白這一點。

正如你所看到的,我不使用自定義BaseAdapter,因爲arrayadapter已經管理我的集合。我只需要告訴列表,有不同的項目視圖類型和集合中哪些項目使用哪種視圖類型。因爲所有持有和管理不同視圖都已由適配器完成 - 例如,所有持有者都不需要使用任何持有者。如果給定的convertView沒有被緩存在適配器中,我們只需要膨脹視圖。

使用這種方式應該有更高的內存效率和性能應該增加,因爲少得多的意見不得不在一個步驟中被誇大。

我希望這有助於

基督教

編輯

無法解釋在中心disapearing gridview的,但不應該再發生