简体   繁体   English

ListActivity 和 Activity 的奇怪行为

[英]Strange behavior of ListActivity and Activity

I'm implementing an application for android and I run into memory issues while populating a list view with data from the internet.我正在为 android 实现一个应用程序,并且在使用来自 Internet 的数据填充列表视图时遇到了 memory 问题。 A strange error that occurs seems to be caused by the lack of recycling of the rows as it should normally happen as it is stated at Google I/O 2009 .发生的一个奇怪错误似乎是由于缺乏行回收造成的,因为它通常应该发生,如Google I/O 2009所述。

When I run the code at http://android.amberfog.com/?p=296 , everything is running smoothly, the row views are recycled and the listView is optimally used.当我在http://android.amberfog.com/?p=296运行代码时,一切运行顺利,行视图被回收,listView 得到最佳使用。

I now want to use the listView within another activity that will have much more things inside, therefore a class that extends just ListActivity, is not enough.我现在想在另一个包含更多内容的活动中使用 listView,因此仅扩展 ListActivity 的 class 是不够的。 So, I have an Activity that has the following code:所以,我有一个具有以下代码的活动:

public class MultipleItemsList extends Activity {
    private Context mContext;
    private MyCustomAdapter mAdapter;
    private ListView listView;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mContext = this;

        listView = (ListView) findViewById(R.id.listView);

        mAdapter = new MyCustomAdapter(mContext);

        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("item " + i);
        }

        listView.setAdapter(mAdapter);
    }  
}

The main.xml is nothing fancy also: main.xml 也没什么特别的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/hello"/>

    <ListView
        android:id="@+id/listView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

The ListActivity that the previous link proposes is the following:上一个链接提出的 ListActivity 如下:

public class MultipleItemsList extends ListActivity {
    private Context mContext;
    private MyCustomAdapter mAdapter;
    private ListView listView;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;

        mAdapter = new MyCustomAdapter(mContext);

        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("item " + i);
        }
        setListAdapter(mAdapter);
    }
}

The adapter is the following in both cases:在这两种情况下,适配器如下:

public class MyCustomAdapter extends BaseAdapter {
    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;
    private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

    private ArrayList<String> mData = new ArrayList<String>();
    private LayoutInflater mInflater;

    private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();

    public static class ViewHolder {
        public TextView textView;
    }

    public MyCustomAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    public void addItem(final String item) {
        mData.add(item);
        notifyDataSetChanged();
    }

    public void addSeparatorItem(final String item) {
        mData.add(item);
        // save separator position
        mSeparatorsSet.add(mData.size() - 1);
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_MAX_COUNT;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public String getItem(int position) {
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        int type = getItemViewType(position);
        Log.d("myCA", "getView " + position + " " + convertView + " type = " + type);
        if (convertView == null) {
            holder = new ViewHolder();
            switch (type) {
                case TYPE_ITEM:
                    convertView = mInflater.inflate(R.layout.item1, null);
                    holder.textView = (TextView)convertView.findViewById(R.id.text);
                    break;
                case TYPE_SEPARATOR:
                    convertView = mInflater.inflate(R.layout.item2, null);
                    holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
                    break;
            }
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }
        holder.textView.setText(mData.get(position));
        return convertView;
    }
}

So, my question is why in the second case of the ListActivity the view recycling takes place without problems, while at the implementation of the Activity, recycling gets screwed up?所以,我的问题是为什么在 ListActivity 的第二种情况下,视图回收没有问题,而在 Activity 的实施中,回收被搞砸了?

The Log shows that when the ListActivity is used, everything is recycled correctly: Log显示,使用ListActivity时,一切都被正确回收:

    07-13 10:14:25.277: DEBUG/myCA(2336): getView 0 null type = 0
    07-13 10:14:25.277: DEBUG/myCA(2336): getView 1 null type = 0
    07-13 10:14:25.277: DEBUG/myCA(2336): getView 2 null type = 0
    07-13 10:14:25.277: DEBUG/myCA(2336): getView 3 null type = 0
    07-13 10:14:25.287: DEBUG/myCA(2336): getView 4 null type = 0
    07-13 10:14:25.287: DEBUG/myCA(2336): getView 5 null type = 0
    07-13 10:14:27.887: DEBUG/myCA(2336): getView 6 null type = 0
    07-13 10:14:28.047: DEBUG/myCA(2336): getView 7 android.widget.LinearLayout@40522c30 type = 0
    07-13 10:14:28.267: DEBUG/myCA(2336): getView 8 android.widget.LinearLayout@405236b8 type = 0
...
...
...

At my implementation of Activity, I see the following:在我的 Activity 实现中,我看到以下内容:

07-13 10:11:47.517: DEBUG/myCA(2296): getView 0 null type = 0
07-13 10:11:47.517: DEBUG/myCA(2296): getView 1 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.517: DEBUG/myCA(2296): getView 2 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.517: DEBUG/myCA(2296): getView 3 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.527: DEBUG/myCA(2296): getView 4 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.527: DEBUG/myCA(2296): getView 5 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.547: DEBUG/myCA(2296): getView 0 android.widget.LinearLayout@405221e8 type = 0
07-13 10:11:47.547: DEBUG/myCA(2296): getView 1 null type = 0
07-13 10:11:47.547: DEBUG/myCA(2296): getView 2 null type = 0
07-13 10:11:47.557: DEBUG/myCA(2296): getView 3 null type = 0
...
...
...

where there is clearly problem with the recycling.回收明显存在问题的地方。

Am I missing something that would make the listView behave properly when the parent activity is just a simple activity and not a ListActivity?当父活动只是一个简单的活动而不是 ListActivity 时,我是否遗漏了一些能让 listView 正常运行的东西? Has anyone come across something like that in the past?过去有没有人遇到过类似的事情?

Thanks for your time.谢谢你的时间。

Both Activity and ListActivity should be fine. ActivityListActivity都应该没问题。 I believe you're leaking the entire activity through the mContext reference.我相信您通过mContext引用泄露了整个活动。 Remove it and see what happens!删除它,看看会发生什么!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM