我的getView中的convertView好像没有正确实现,你能告诉我为什么吗?

My convertView in getView does not seem to be implemented properly, can you tell me why?

我的 listView 似乎加载正确,但在测试时我认为它有问题。

我正在看这个教程:http://android.amberfog.com/?p=296#more-296

我添加了以下行:

System.out.println("getView " + position + " " + convertView);

按照教程,在 logcat 中,我应该在向下滚动 listView 时看到 convertView 值,例如:

System.out(947): getView 20 android.widget.LinearLayout@437430f8

但在我的 logcat 中,我所有的 convertViews 都是 null。我什至没有滚动 listView,我的 122 行立即膨胀 - 根据 logcat 判断。所有值的形式为:

System.out: getView number is :21convertView is : null

我是不是做错了什么?

这是我的代码:

public class SelectPhoneContactAdapter extends BaseAdapter {

    //define a list made out of SelectPhoneContacts and call it theContactsList
    public List<SelectPhoneContact> theContactsList;
    //define an array list made out of SelectContacts and call it arraylist
    private ArrayList<SelectPhoneContact> arraylist;
    Context _c;

    //define a ViewHolder to hold our name and number info, instead of constantly querying
    // findviewbyid. Makes the ListView run smoother
    // ViewHolder viewHolder;

    public SelectPhoneContactAdapter(final List<SelectPhoneContact> selectPhoneContacts, Context context) {
        theContactsList = selectPhoneContacts;
        _c = context;
        this.arraylist = new ArrayList<SelectPhoneContact>();
        this.arraylist.addAll(theContactsList);

    }


    @Override
    public int getCount() {
        System.out.println("the amount in arraylist :" + theContactsList.size());
        return arraylist.size();
    }

    @Override
    public Object getItem(int i) {
        return theContactsList.get(i);
    }

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

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

    static class ViewHolder {
        //        In each cell in the listview show the items you want to have
//        Having a ViewHolder caches our ids, instead of having to call and load each one again and again
        TextView title, phone;
        CheckBox check;
    }

    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {
        System.out.println("getView number is :" + i + "convertView is : " + convertView);

        ViewHolder viewHolder = null;

        if (convertView == null) {

            //if there is nothing there (if it's null) inflate the view with the layout
            LayoutInflater li = (LayoutInflater) _c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = li.inflate(R.layout.phone_inflate_listview, null);

            viewHolder = new ViewHolder();

            //      So, for example, title is cast to the name id, in phone_inflate_listview,
//        phone is cast to the id called no etc
            viewHolder.title = (TextView) convertView.findViewById(R.id.name);
            viewHolder.phone = (TextView) convertView.findViewById(R.id.no);

            viewHolder.check = (CheckBox) convertView.findViewById(R.id.checkBoxContact);
            viewHolder.check.setVisibility(View.GONE);

            //remember the state of the checkbox
            viewHolder.check.setOnCheckedChangeListener((NewContact) _c);

            convertView.setTag(viewHolder);

        } else {

            viewHolder = (ViewHolder) convertView.getTag();

        }
//        store the holder with the view
            final SelectPhoneContact data = (SelectPhoneContact) theContactsList.get(i);
            //in the listview for contacts, set the name
            viewHolder.title.setText(data.getName());
            //in the listview for contacts, set the number
            viewHolder.phone.setText(data.getPhone());

            viewHolder.check.setChecked(data.isSelected());
            viewHolder.check.setTag(data);

        return convertView;

    }
}

在我的 activity 中,我使用了一个函数来测量列表视图在加载到屏幕之前的高度,也许这是问题的一部分。不知道能不能解决,如果能解决就好了

来自我的 NewContact.java:

 @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            adapter = new SelectPhoneContactAdapter(selectPhoneContacts, NewContact.this);

            adapter.notifyDataSetChanged();
            listView.setAdapter(adapter);

            justifyListViewHeightBasedOnChildren(listView);

        }

justifyListViewHeightBasedOnChildren 函数:

//this is the function we call to measure the height of the listview
//we need this because there are problems with a listview within a scrollview
public static void justifyListViewHeightBasedOnChildren (ListView listView) {

    ListAdapter adapter = listView.getAdapter();

    if (adapter == null) {
        return;
    }
    ViewGroup vg = listView;
    int totalHeight = 0;
    for (int i = 0; i < adapter.getCount(); i++) {
        View listItem = adapter.getView(i, null, vg);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams par = listView.getLayoutParams();
    par.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));
    listView.setLayoutParams(par);
    listView.requestLayout();

    System.out.println("the getcount is " + adapter.getCount());
    System.out.println("the height is " + par.height);
}

ListView调用getView()方法时,convertView参数是否有non-null值取决于ListView是否为试图 "recycle" 一个视图。当屏幕上 之前 的视图滚动(足够远) off-screen 并且 ListView 确信它暂时不需要并且可以是 re-used ("recycled") 以显示即将滚动 on-screen.

的 "new" 视图的值

这里的想法是 ListView 的所有 children 具有相同的 结构 ;他们在相同的地方有相同的View。只有那些视图的 contents 发生了变化。因此,与其膨胀另一个视图,不如回收一个不再使用的旧视图。

不管它是如何发生的,如果你的 ListView 足够大,可以一次容纳所有 children,那么回收是不可能的。你基本上创造了一个美化 LinearLayout。这是否是一个 问题 完全取决于您和您的要求。但是当这种情况发生时,整个ListView(视图回收)的"point"就不会发生了。

所有这些就是说:在对 getView() 的所有 122 次调用中看到 convertView 的所有 122 个值的 null 意味着您使用的 ListView 不同于预期的。如果您的应用程序仍能完美运行,则完全没有必要更改它。但请注意,您并未在 Google 框架的预期范围内工作。