2014-09-05 31 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的,但不应该再发生