使用自定义适配器会使用更多 RAM?

发布于 2024-11-17 20:56:43 字数 3197 浏览 4 评论 0原文

我的应用程序在第一次午餐时使用了 6.5mb,然后当我输入具有 3 个选项卡的活动(其中一个选项卡显示列表视图)时,它使用了 14mb!

当我从 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 的 ram。将我的代码更改为使用自定义适配器后,它使用了 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;

}

  }

谁能告诉我为什么使用自定义适配器时使用了这么多内存?这个自定义适配器有问题吗?

编辑1:这是一个比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); “ 为什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

莫言歌 2024-11-24 20:56:43

您没有在 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进行布局。

请参阅此演示文稿有关列表视图适配器效率的更多信息。

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.

燃情 2024-11-24 20:56:43

不要为每个条目生成 UI 元素

您为每个条目返回一个新的relativeView。这会

  1. 使用更多的内存
  2. ,给垃圾收集器带来更大的压力

使用正常的方式实现 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。源代码是免费提供的。几乎每个适配器都有这些代码块。

黑客快乐!

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!

赏烟花じ飞满天 2024-11-24 20:56:43

您可能想做的第一件事是开始使用传递给 getView 的 ConvertView 而不是创建新视图。您最终将获得更高的性能(来自更少的垃圾收集和更少的视图构造),并且可能会降低内存使用量。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文