我的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 框架的预期范围内工作。
我的 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.
这里的想法是 ListView
的所有 children 具有相同的 结构 ;他们在相同的地方有相同的View
。只有那些视图的 contents 发生了变化。因此,与其膨胀另一个视图,不如回收一个不再使用的旧视图。
不管它是如何发生的,如果你的 ListView
足够大,可以一次容纳所有 children,那么回收是不可能的。你基本上创造了一个美化 LinearLayout
。这是否是一个 问题 完全取决于您和您的要求。但是当这种情况发生时,整个ListView
(视图回收)的"point"就不会发生了。
所有这些就是说:在对 getView()
的所有 122 次调用中看到 convertView
的所有 122 个值的 null
意味着您使用的 ListView
不同于预期的。如果您的应用程序仍能完美运行,则完全没有必要更改它。但请注意,您并未在 Google 框架的预期范围内工作。