我开发了一个Android应用程序,其中图像和文本显示在网格视图中,当用户向下滚动时,显示下十个项目(图像和文本)。在adapter.notifyDataSetChanged()调用之后调用适配器的getView方法时出现问题。适配器回收数据,但位置重新排列并在网格视图中重复。直到我添加条件来检查convertView是否为null,我才遇到这个问题。
活动类:
public class DynamicListViewActivity extends Activity implements
OnScrollListener {
int visibleElements;
int scrollState;
int count;
TextAdapter adapter = new TextAdapter();
int total=200;// total items limit in grid view
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid);
count=10;
GridView grid = (GridView) findViewById(R.id.gridview);
grid.setAdapter(adapter);
grid.setOnScrollListener(this);
}
public void onScroll(AbsListView view, int firstVisible, int visibleCount,
int totalCount) {
visibleElements= visibleCount;
}
public void onScrollStateChanged(AbsListView v, int s) {
Log.d("ScrollState", s+"");
scrollState=s;
isScrollStateComplete();
}
public void isScrollStateComplete(){
if(visibleElements>0 && scrollState==SCROLL_STATE_IDLE && total>count){
int diff=total-count;
count+=(diff>=10)?10:diff;//update count to next ten items
adapter.notifyDataSetChanged();
}
}
class TextAdapter extends BaseAdapter {
public int getCount() {
return count;
}
public Object getItem(int pos) {
return pos;
}
public long getItemId(int pos) {
return pos;
}
public View getView(int pos, View convertView, ViewGroup p) {
View v = convertView;
System.out.println("pos : "+pos+" boolean "+(v==null));// log to check position and convertView
if(v==null){
v =((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.textlayout,null);
ImageView iv = (ImageView) v.findViewById(R.id.album_thumbnail);
iv.setImageDrawable(getResources().getDrawable(R.drawable.icon));
TextView tvAlbumName = (TextView)v.findViewById(R.id.album_name);
tvAlbumName.setText("postion "+pos);
TextView tvAlbumDesc = (TextView)v.findViewById(R.id.album_description);
tvAlbumDesc.setText("");
}
return v;
}
}
}
在滚动网格视图之前正确显示。记录:
08-05 14:24:34.440: INFO/ActivityManager(58): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.mis.list.demo/.DynamicListViewActivity }
08-05 14:24:34.642: INFO/System.out(685): pos : 0 boolean true
08-05 14:24:34.710: INFO/System.out(685): pos : 0 boolean false
08-05 14:24:34.710: INFO/System.out(685): pos : 1 boolean true
08-05 14:24:34.730: INFO/System.out(685): pos : 2 boolean true
08-05 14:24:34.800: INFO/System.out(685): pos : 3 boolean true
08-05 14:24:34.860: INFO/System.out(685): pos : 4 boolean true
08-05 14:24:34.880: INFO/System.out(685): pos : 5 boolean true
08-05 14:24:34.910: INFO/System.out(685): pos : 6 boolean true
08-05 14:24:34.920: INFO/System.out(685): pos : 7 boolean true
08-05 14:24:34.960: INFO/System.out(685): pos : 0 boolean true
08-05 14:24:35.030: INFO/ActivityManager(58): Displayed activity com.mis.list.demo/.DynamicListViewActivity: 520 ms (total 520 ms)
滚动的第一个结束后
08-05 14:26:15.740: DEBUG/ScrollState(685): 1
08-05 14:26:15.830: DEBUG/dalvikvm(685): GC_EXTERNAL_ALLOC freed 3624 objects / 257464 bytes in 71ms
08-05 14:26:16.210: INFO/System.out(685): pos : 8 boolean false
08-05 14:26:16.210: INFO/System.out(685): pos : 9 boolean true
08-05 14:26:16.250: DEBUG/ScrollState(685): 0
08-05 14:26:16.260: INFO/System.out(685): pos : 0 boolean true
08-05 14:26:16.271: INFO/System.out(685): pos : 0 boolean false
08-05 14:26:16.271: INFO/System.out(685): pos : 1 boolean false
08-05 14:26:16.271: INFO/System.out(685): pos : 2 boolean false
08-05 14:26:16.271: INFO/System.out(685): pos : 3 boolean false
08-05 14:26:16.271: INFO/System.out(685): pos : 4 boolean false
08-05 14:26:16.271: INFO/System.out(685): pos : 5 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 6 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 7 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 8 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 9 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 10 boolean false
08-05 14:26:16.280: INFO/System.out(685): pos : 11 boolean true
08-05 14:26:16.371: DEBUG/dalvikvm(685): GC_EXTERNAL_ALLOC freed 644 objects / 33224 bytes in 41ms
08-05 14:26:45.270: WARN/KeyCharacterMap(685): No keyboard for id 0
08-05 14:26:45.270: WARN/KeyCharacterMap(685): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
08-05 14:26:45.341: INFO/System.out(685): pos : 12 boolean true
08-05 14:26:45.351: INFO/System.out(685): pos : 13 boolean true
08-05 14:26:45.371: INFO/System.out(685): pos : 14 boolean true
08-05 14:26:45.380: INFO/System.out(685): pos : 15 boolean true
08-05 14:26:45.450: INFO/System.out(685): pos : 16 boolean false
08-05 14:26:45.450: INFO/System.out(685): pos : 17 boolean false
08-05 14:26:45.460: INFO/System.out(685): pos : 18 boolean false
08-05 14:26:45.460: INFO/System.out(685): pos : 19 boolean false
但是网格显示重复值而不是按顺序显示。 对不起我不允许发布图片,因为我是新用户。
在日志中我看到位置0 convertView == null为真。
如何设置此权限,因为我计划在当前使用的图像视图的android图标位置下载图像。
请帮忙。
答案 0 :(得分:13)
您对convertView的解释不正确。
public View getView(int pos, View convertView, ViewGroup p) {
View v = convertView;
//If convertView is null create a new view, else use convert view
if(v==null)
v =((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.textlayout,null);
ImageView iv = (ImageView) v.findViewById(R.id.album_thumbnail);
iv.setImageDrawable(getResources().getDrawable(R.drawable.icon));
TextView tvAlbumName = (TextView)v.findViewById(R.id.album_name);
tvAlbumName.setText("postion "+pos);
TextView tvAlbumDesc = (TextView)v.findViewById(R.id.album_description);
tvAlbumDesc.setText("");
return v;
}
是你应该做的。
由于您正在做的事情,在convertView
不为null的情况下,您只是在不更新数据的情况下返回convertView,因此您的图像被重复。仅在convertView
为空的情况下才设置数据。
适配器和列表视图系统之间的契约:如果传递的convertView
为null,则创建一个新的,否则重复使用它。
答案 1 :(得分:4)
Vikram Bodicherla 是正确的(+1),您的实施不正确,他的代码示例正确修复了您的问题。不过,我想推荐以下Google I / O 2010演讲:The world of ListView。这是一个小时,但您将更深入地了解ListView
如何工作以及如何编写适配器以正确配合它。
答案 2 :(得分:0)
如果Android确定表示行的View不再可见,则允许getView()方法通过convertView参数重用它。
性能优化适配器将新数据分配给convertView。这样可以避免膨胀XML文件并创建新的Java对象。
如果没有View可供重用,Android会将null传递给convertView参数。因此,适配器实现需要检查这一点。