Android:自定义 SimpleCursorAdapter 中的 newView 和 bindView 问题
我从我发现的唯一示例之一创建了一个自定义 SimpleCursorAdapter。
当调用我的 ListActivity 时,将为每个数据库条目调用 newView 和 bindView,并为每个条目再次调用。我有几个问题:
- 这个例子正确吗(如果不对,我在哪里可以找到)?
-如果bindView调用总是在newView调用之前,为什么在两个函数中做同样的事情?
-为什么序列 newView-bindView 对每个项目调用两次?
-为什么一些CursorAdapter示例使用getView而不是newView和bindView?
基本上,应该如何使用 SimpleCursorAdapter,以及我的代码有什么问题?
感谢
ListActivity
public class ContactSelection extends ListActivity {
private WhipemDBAdapter mDbHelper;
private FriendAdapter friendAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDbHelper = new WhipemDBAdapter(this);
mDbHelper.open();
setContentView(R.layout.contact_list);
Cursor c = mDbHelper.fetchAllFriends();
startManagingCursor(c);
String[] from = new String[] {};
int[] to = new int[] {};
this.friendAdapter = new FriendAdapter(this, R.layout.contact_row, c, from, to);
setListAdapter(this.friendAdapter);
getListView().setItemsCanFocus(false);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
@Override
protected void onResume() {
super.onResume();
mDbHelper.open();
}
@Override
protected void onPause() {
super.onPause();
mDbHelper.close();
}
}
自定义 SimpleCursorAdapter
public class FriendAdapter extends SimpleCursorAdapter implements OnClickListener {
private Context mContext;
private int mLayout;
public FriendAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.mContext = context;
this.mLayout = layout;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(mLayout, parent, false);
String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));
TextView name_text = (TextView) v.findViewById(R.id.contact_name);
if (name_text != null) {
name_text.setText(name);
}
ImageView im = (ImageView) v.findViewById(R.id.contact_pic);
Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
if (im != null) {
im.setImageDrawable(drawable);
}
CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
if (im != null) {
bCheck.setTag(fb_id);
}
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
bCheck.setChecked(true);
bCheck.setOnClickListener(this);
return v;
}
@Override
public void bindView(View v, Context context, Cursor c) {
String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));
TextView name_text = (TextView) v.findViewById(R.id.contact_name);
if (name_text != null) {
name_text.setText(name);
}
ImageView im = (ImageView) v.findViewById(R.id.contact_pic);
Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
if (im != null) {
im.setImageDrawable(drawable);
}
CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
if (im != null) {
bCheck.setTag(fb_id);
}
ArrayList<String> dude = ((GlobalVars) mContext.getApplicationContext()).getSelectedFriendList();
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
bCheck.setChecked(true);
bCheck.setOnClickListener(this);
}
@Override
public void onClick(View v) {
CheckBox cBox = (CheckBox) v;
String fb_id = (String) cBox.getTag();
if (cBox.isChecked()) {
if (!((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
((GlobalVars) mContext.getApplicationContext()).addSelectedFriend(fb_id);
} else {
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
((GlobalVars) mContext.getApplicationContext()).removeSelectedFriend(fb_id);
}
}
private Drawable LoadImageFromWebOperations(String url)
{
try
{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
}catch (Exception e) {
System.out.println("Exc="+e);
return null;
}
}
}
I created a custom SimpleCursorAdapter from one of the only example I found.
When my ListActivity is called, newView and bindView are called for every of my DB entry, and called again for every entry. I've got a few questions:
-is the example right (if not, where can I find one)?
-if bindView call is always preceded by newView call, why doing the same in both functions?
-why is the sequence newView-bindView called twice for every item?
-why some CursorAdapter examples use getView instead of newView and bindView?
Basically, how should SimpleCursorAdapter be used, and what's wrong with my code?
Thanks
ListActivity
public class ContactSelection extends ListActivity {
private WhipemDBAdapter mDbHelper;
private FriendAdapter friendAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDbHelper = new WhipemDBAdapter(this);
mDbHelper.open();
setContentView(R.layout.contact_list);
Cursor c = mDbHelper.fetchAllFriends();
startManagingCursor(c);
String[] from = new String[] {};
int[] to = new int[] {};
this.friendAdapter = new FriendAdapter(this, R.layout.contact_row, c, from, to);
setListAdapter(this.friendAdapter);
getListView().setItemsCanFocus(false);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
@Override
protected void onResume() {
super.onResume();
mDbHelper.open();
}
@Override
protected void onPause() {
super.onPause();
mDbHelper.close();
}
}
Custom SimpleCursorAdapter
public class FriendAdapter extends SimpleCursorAdapter implements OnClickListener {
private Context mContext;
private int mLayout;
public FriendAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.mContext = context;
this.mLayout = layout;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(mLayout, parent, false);
String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));
TextView name_text = (TextView) v.findViewById(R.id.contact_name);
if (name_text != null) {
name_text.setText(name);
}
ImageView im = (ImageView) v.findViewById(R.id.contact_pic);
Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
if (im != null) {
im.setImageDrawable(drawable);
}
CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
if (im != null) {
bCheck.setTag(fb_id);
}
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
bCheck.setChecked(true);
bCheck.setOnClickListener(this);
return v;
}
@Override
public void bindView(View v, Context context, Cursor c) {
String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));
TextView name_text = (TextView) v.findViewById(R.id.contact_name);
if (name_text != null) {
name_text.setText(name);
}
ImageView im = (ImageView) v.findViewById(R.id.contact_pic);
Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
if (im != null) {
im.setImageDrawable(drawable);
}
CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
if (im != null) {
bCheck.setTag(fb_id);
}
ArrayList<String> dude = ((GlobalVars) mContext.getApplicationContext()).getSelectedFriendList();
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
bCheck.setChecked(true);
bCheck.setOnClickListener(this);
}
@Override
public void onClick(View v) {
CheckBox cBox = (CheckBox) v;
String fb_id = (String) cBox.getTag();
if (cBox.isChecked()) {
if (!((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
((GlobalVars) mContext.getApplicationContext()).addSelectedFriend(fb_id);
} else {
if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
((GlobalVars) mContext.getApplicationContext()).removeSelectedFriend(fb_id);
}
}
private Drawable LoadImageFromWebOperations(String url)
{
try
{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
}catch (Exception e) {
System.out.println("Exc="+e);
return null;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
重写 getView() 函数使您可以“重新使用”已经膨胀的列表项(当您来回滚动列表时从当前视图端口“滚动出”的列表项) )。
通过这样做,您将节省大量内存资源和处理器运行时间,因为膨胀是一项相当耗时的操作。对于您重复使用的每个
convertView
,您还可以节省 GC 运行时间(因为垃圾收集器不必收集该特定列表项)。您还可以创建一个“视图集合”类(下面示例中的
ViewHolder
类),它将保存膨胀列表项中每个视图的引用。这样,您就不必每次用新值更新列表项时(通常是在滚动列表时)都找到它们。findViewById()
也是一个相当耗时的操作。另外,我认为您可以缓存更多变量,例如布局充气器和列索引。一切都是为了节省时间:-)
Overriding the
getView()
function gives you the possibility of "re-using" already inflated list items (the list items that are "scrolled out" from the current view port when you scroll your list back and forth).By doing so you'll save a lot of memory resources and processor run time, since inflating is a quite time consuming operation. For each and every
convertView
you re-use you also save GC run-time (since the garbage collector doesn't have to collect that specific list item).You can also create a "view collection" class (the
ViewHolder
class in the below example) which will hold the references for each view in your inflated list item. This way you don't have to find them each and every time you update a list item with new values (typically whan you scroll the list).findViewById()
is also a rather time consuming operation.Also I think you can cache more variables, like the layout inflater, and the column indices. Everything to save time :-)
这个例子几乎是正确的。您不需要在
newView()
中进行绑定,因为就像您提到的那样,bindView()
将被调用。如果您看到每个项目调用两次 newView/bindView 序列,则您可能正在使用ListView
并将其高度设置为wrap_content
,这始终是一个坏主意。最后,newView()
和bindView()
特定于CursorAdapter
:它实现getView()
并调用newView()
或bindView()
为您服务。但是,重写getView()
也是完全有效的。这就是其他适配器的工作方式。请注意,仅针对将在屏幕上显示的每个项目调用
getView()
(因此还有 bindView/newView)。The example is almost right. You don't need to do the binding in
newView()
, since like you mentioned,bindView()
will be called. If you see the sequence newView/bindView called twice per item, you are probably usingListView
with its height set towrap_content
, which is always a bad idea. Finally,newView()
andbindView()
are specific toCursorAdapter
: it implementsgetView()
and calls eithernewView()
orbindView()
for you. However, overridinggetView()
is perfectly valid as well. This is how other adapters work.Note that
getView()
(and therefore bindView/newView) are only invoked for each item that will be displayed on the screen.