我在第一个午餐的应用程序使用6.5mb,然后当我输入一个包含3个选项卡的活动时,带有显示列表视图的选项卡,它使用14 mb !!
当我从使用SimpleAdapter的“错误代码”转到我的自定义适配器时,就发生了这种情况。
我想要的是列表视图中每侧2个字符串。字符串是一个数组,这是我使用的方式,人们告诉我这是一个不正确的方法:
String[] array= getResources().getStringArray(R.array.Names_List);
int lengthtmp= array.length;
for(int i=0;i<lengthtmp;i++)
{
counter++;
AddToList(array[i]);
}
adapter = new SimpleAdapter(this,list,R.layout.start_row,new String[] {"number","suraname"},new int[] {R.id.Start_Numbering,R.id.Start_Name});
private void AddToList(String name) {
HashMap<String,String> temp = new HashMap<String,String>();
temp.put("number", Integer.toString(SortingPictures[counter-1]));
temp.put("suraname", name);
list.add(temp);
}
使用此代码,活动需要10mb的内存。更改我的代码以使用自定义适配器后,它使用14 MB:
public class ListView_Start_Adapter extends BaseAdapter{
private String[] SuraNames;
private int[] PageNumber;
private Context mContext;
RelativeLayout relativeView;
TextView tv_SuraName;
TextView tv_PageNumber;
RelativeLayout.LayoutParams param;
public ListView_Start_Adapter(Context context, String[] SuraNames, int[] PageNumber){
mContext=context;
this.SuraNames=SuraNames;
this.PageNumber=PageNumber;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return SuraNames.length;
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return SuraNames[arg0];
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return PageNumber[arg0];
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
relativeView= new RelativeLayout(mContext);
tv_SuraName = new TextView(mContext);
tv_PageNumber = new TextView(mContext);
tv_SuraName.setText(SuraNames[position]);
tv_PageNumber.setText(Integer.toString(PageNumber[position]));
param = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
param.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
relativeView.addView(tv_SuraName, param);
relativeView.addView(tv_PageNumber);
return relativeView;
}
}
任何人都可以告诉我为什么使用自定义适配器时会使用这么多ram?这个自定义适配器有什么问题吗?
EDIT1:这是一个比dziobas建议的更好的代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = mInflater.inflate(R.layout.start_row, parent,false);
holder=new ViewHolder();
holder.tv_SuraName =(TextView)convertView.findViewById(R.id.Start_Name);
holder.tv_PageNumber = (TextView)convertView.findViewById(R.id.Start_Numbering);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv_SuraName.setText(SuraNames[position]);
holder.tv_PageNumber.setText(Integer.toString(PageNumber[position]));
return convertView;
}
我在这一行得到了ExceptionNullPointer:“convertView = mInflater.inflate(R.layout.start_row,parent,false); “为什么?
答案 0 :(得分:3)
您没有在getView中回收视图。
这样会好得多:
public class ListView_Start_Adapter extends BaseAdapter {
private String[] SuraNames;
private int[] PageNumber;
RelativeLayout.LayoutParams param;
Context mContext;
public ListView_Start_Adapter(Context context, String[] SuraNames, int[] PageNumber) {
mContext = context;
this.SuraNames = SuraNames;
this.PageNumber = PageNumber;
param = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
param.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
}
@Override
public int getCount() {
return SuraNames.length;
}
@Override
public Object getItem(int arg0) {
return SuraNames[arg0];
}
@Override
public long getItemId(int arg0) {
return PageNumber[arg0];
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RelativeLayout rowView;
if(convertView == null) {
//create view
rowView = new RelativeLayout(mContext);
holder = new ViewHolder();
holder.tv_SuraName = new TextView(mContext);
holder.tv_PageNumber = new TextView(mContext);
rowView.addView(holder.tv_SuraName, param);
rowView.addView(holder.tv_PageNumber);
rowView.setTag(holder);
} else {
//recycle view
rowView = (RelativeLayout) convertView;
holder = (ViewHolder) convertView.getTag();
}
//fill views
holder.tv_SuraName.setText(SuraNames[position]);
holder.tv_PageNumber.setText(Integer.toString(PageNumber[position]));
return rowView;
}
class ViewHolder {
RelativeLayout relativeView;
TextView tv_SuraName;
TextView tv_PageNumber;
}
}
并更改视图创建。使用LayoutInflater并使用xml进行布局。
有关listview适配器效率的详细信息,请参阅this presentation。
答案 1 :(得分:2)
不要为每个条目生成UI元素
您为每个条目返回一个新的relativeView。这将
使用常规方式实现getView
// In the class
private LayoutInflater inflater;
// in the constructor
inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// getView()
if (view == null) {
view = inflater.inflate(R.layout.element_layout, parent, false);
}
SimpleAdapter源代码可用
看看SimpleAdapter.java。源代码是免费提供的。几乎每个Adapter都有这些代码块。
快乐的黑客攻击!
答案 2 :(得分:0)
您可能想要做的第一件事是开始使用传递给getView的convertView而不是创建新视图。您将获得更高的性能(从更少的垃圾收集和更少的视图构造),并可能降低内存使用率。