Android getView中的convertView似乎没有正确实现,您能告诉我原因吗?

Android getView中的convertView似乎没有正确实现,您能告诉我原因吗?,android,listview,convertview,Android,Listview,Convertview,我的listView似乎加载正确,但在测试中我认为它有问题 我正在看本教程: 我添加了一行: System.out.println("getView " + position + " " + convertView); 根据教程,在logcat中,我应该在向下滚动listView时看到convertView值,如: 但是在我的logcat中,我所有的视图都是空的。我甚至不滚动listView,我的122行数据立即膨胀了——这是由logcat判断的。所有值的形式如下: System.out: g

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

我正在看本教程:

我添加了一行:

System.out.println("getView " + position + " " + convertView);
根据教程,在logcat中,我应该在向下滚动listView时看到convertView值,如:

但是在我的logcat中,我所有的视图都是空的。我甚至不滚动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;

    }
}
justifyListViewHeightBasedOnChildren函数:

当ListView调用getView方法时,convertView参数是否具有非null值取决于ListView是否尝试回收视图。当以前在屏幕上的视图被滚动到足够远的屏幕外,ListView确信它在一段时间内不再需要,并且可以被循环使用以显示即将在屏幕上滚动的新视图的值时,就会发生循环

这里的想法是ListView的所有子级都具有相同的结构;他们在相同的地方有相同的观点。只有那些观点的内容在改变。因此,与其夸大另一种观点,不如将不再使用的旧观点回收利用

不管它是如何发生的,如果您的ListView足够大,可以同时容纳所有子项,那么回收是不可能的。您基本上创建了一个美化的线性布局。这是否是一个问题实际上取决于您和您的要求。但是,当这种情况发生时,ListView的整个回收过程就不会发生了


所有这一切都意味着:在对getView的所有122个调用中,convertView的所有122个值都为null,这意味着您使用的ListView与预期的不同。如果你的应用程序仍然运行良好,就没有必要对其进行严格的更改。但是要知道,你没有在谷歌框架的预期范围内工作。

我很想知道你的设计和项目视图是如何实现的。在我看来,这似乎是您设法使ListView足够高,它可以显示所有122行而无需滚动,因为您的项目非常短,或者您的ListView非常高,可能在某种滚动容器中。@Ben P.是的,我决定使用一个与我的布局一起滚动的listview是最好的图形用户界面,因此我的listview没有滚动条。我有一个函数,可以精确测量listview的高度,然后加载它。我知道人们不推荐这个,但我认为它最适合我的需要。好的。我将编辑我的问题,以便您可以查看代码。
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;

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

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

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

            justifyListViewHeightBasedOnChildren(listView);

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