问题
I have a GridView in android which I fill it with data retrieved from a xml resource.
For example I have 15 items in the GridView which are placed in order. The overall height exceeds the Screen height so i have to scroll to see the rest of the items.
The problem is when I scroll back up, the order of the invisible rows have changed. It's a mysterious behavior as sometimes items swap rows with each other.
Here is my getView
method:
public class ImageAdapter extends BaseAdapter {
public ImageAdapter(Context c, NodeList cuu) {
cu = cuu;
}
public int getCount() {
Log.d("Node Count",cu.getLength()+"");
return cu.getLength();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View myView = convertView;
if (convertView == null) {
Node nd = cu.item(position);
Log.d("nodes","Pos: "+(position)+" Name: "+nd.getNodeName()+" Title: "+nd.getAttributes().getNamedItem("title").getTextContent());
int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id").getTextContent());
LayoutInflater li = getLayoutInflater();
myView = li.inflate(R.layout.grid_item, null);
ImageView imageView = (ImageView) myView.findViewById(R.id.grid_item_image);
myView.setLayoutParams(new GridView.LayoutParams(70, 100));
id.download(nd.getAttributes().getNamedItem("icon").getTextContent(),imageView);
TextView textView = (TextView) myView.findViewById(R.id.grid_item_text);
textView.setText(nd.getAttributes().getNamedItem("title").getTextContent());
myView.setTag((Object) catID);
}else{
//Log.d("nodes","Pos: "+(position));
}
return myView;
}
private NodeList cu = null;
}
Update: Well, it's rather odd. After some more debugging I noticed that in the GridView, the Adapter skips the 13th position, meaning it returns 1 instead of 13 and then moves on to 14!!! (I guess the 13 is bad luck!)
回答1:
If that is all the code you have in the getView
method you're not implementing it right:
public View getView(int position, View convertView, ViewGroup parent) {
View myView = convertView;
if (myView == null) {
Node nd = cu.item(position);
int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id")
.getTextContent());
LayoutInflater li = getLayoutInflater();
myView = li.inflate(R.layout.grid_item, null);
myView.setLayoutParams(new GridView.LayoutParams(70, 100));
myView.setTag((Object) catID);
}
Node nd = cu.item(position);
Log.d("nodes", "Pos: " + (position) + " Name: " + nd.getNodeName()
+ " Title: "
+ nd.getAttributes().getNamedItem("title").getTextContent());
ImageView imageView = (ImageView) myView
.findViewById(R.id.grid_item_image);
id.download(nd.getAttributes().getNamedItem("icon")
.getTextContent(), imageView);
TextView textView = (TextView) myView
.findViewById(R.id.grid_item_text);
textView.setText(nd.getAttributes().getNamedItem("title")
.getTextContent());
return myView;
}
I don't know if the code above works, yours is a bit strange. Anyway, I think the behavior you see its normal because all you do in your adapter is populating the first visible elements and then the adapter will be reusing the exact same elements when you scroll up and down because of the recycling. In the getView
you should:
- Check if the
convertView
isnull
:- If it is
null
it's time to inflate a newView
for thisGridView
's element. You could also use the holder pattern to cache looking for the composingViews
(instead of searching withfindViewById
everytime)(You use thesetTag
element for the inflated View but it's a piece of data from theNode
data element ?!? What do you plan to do with it?!?) - If it isn't
null
you'll do nothing(or if you implement the holder pattern you would get the tag with the already searchedViews
)
- If it is
And this is what you should do in that if/else statement
- After the part above you'll populate the
Views
with data(so they hold the apropriate data for that position).
回答2:
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view= inflate your xml
} else {
view=convertView;
}
// all remaining code like
// view.findViewById(R.id.btn).setText("MyButton");
// must be outside if-else
}
回答3:
Your adapter implementation is fatally flawed.
In getView()
, if convertView
is null
, you inflate a layout and populate its widgets. This is fine.
In getView()
, if convertView
is not null
, you do absolutely nothing. This is exceedingly wrong.
What you should be doing in getView()
, if convertView
is not null
, is still populating the cell's widgets. convertView
represents a cell to be recycled, so you can skip the inflation and save CPU time, but you still have to update that cell's widgets to reflect whatever position you are supposed to be setting up in this specific getView()
call.
回答4:
I have just deleted the
if(convertView==null)
it works
回答5:
If your Grid item has several views in it you can use getTag()
and setTag()
methods. In this case, grid items won't change their places on scrolling anymore and the performance still be fine:
public class SomeAdapter extends BaseAdapter {
public static class ViewHolder {
public TextView tvTitle;
public ImageView imgPoster;
}
//...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder grid;
LayoutInflater inflator = activity.getLayoutInflater();
if (convertView == null) {
grid = new ViewHolder();
convertView = inflator.inflate(R.layout.grid_item, null);
grid.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
grid.imgPoster = (ImageView) convertView.findViewById(R.id.img_poster);
convertView.setTag(grid); // <<-- H E R E
} else {
grid = (ViewHolder) convertView.getTag(); // <<-- H E R E
}
grid.tvTitle.setText(dataItem.getTitle());
grid.imgPoster.setImage(dataItem.getImage());
return convertView;
}
}
回答6:
I used this solution, based on another samples, and worked:
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
view = inflate your xml and apply the View Holder pattern
} else {
view = convertView;
}
// retrieve the object by Holder pattern
// extra code here
}
来源:https://stackoverflow.com/questions/10672273/why-items-change-order-upon-scrolling-in-android-gridview