开发者

Using Custom Adapter uses more RAM?

开发者 https://www.devze.com 2023-03-16 14:54 出处:网络
my application on the first lunch uses 6.5mb, and then when I enter an activity with 3 tabs, with a tab that displays a listview, it uses 14 mb!!

my application on the first lunch uses 6.5mb, and then when I enter an activity with 3 tabs, with a tab that displays a listview, it uses 14 mb!!

This happened when I went from a "bad code" with SimpleAdapter to my Custom Adapter.

What I want is 2 strings on each side in a listview. the strings are in an array, here is the way I was using that people told me is an incorrect way to do:

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);

  }

With this code, the activity takes 10mb of ram. After changing my code to use a Custom adapter, it uses 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;

}

  }

Can anyone tell me why so much ram used when using a Custom adapter? Is there something wrong with this Custom adapter?

EDIT1: Is this a better code that the one suggested by 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;
}

I get ExceptionNullPointer in this line: " convertView = mInflater.inflate(R.layout.start_row, parent,false); " Why?


You're not recycling view in getView.

It'll much better like this:

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;
    }
}

And change view creation. Use LayoutInflater and use xml for layout.

See this presentation for more info about listview adapter efficiency.


Don't generate a UI element for every entry

You return a fresh relativeView for every single entry. This will

  1. Use more memory
  2. Put more pressure on the garbage collector

Use the normal way to implement 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);
    }

The SimpleAdapter source code is available

Just look at the SimpleAdapter.java. The sourcecode is freely available. Just about every Adapter has these code block.

Happy hacking!


The first thing that you might want to do is start using the convertView passed into getView instead of creating new views. You'll end up with higher performance (from fewer garbage collections and fewer view constructions) and probably lower memory usage.

0

精彩评论

暂无评论...
验证码 换一张
取 消