Android 调用notifyDataSetChanged时GridView顺序已更改

Android 调用notifyDataSetChanged时GridView顺序已更改,android,gridview,Android,Gridview,我想在android中使用GridView创建一个月历。 这是我的代码:(对不起我的名字) 活动类别: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_month_calendar); GridView calendar = (GridView) findView

我想在android中使用GridView创建一个月历。 这是我的代码:(对不起我的名字) 活动类别:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_month_calendar);

    GridView calendar = (GridView) findViewById(R.id.month_view);
    final List<Item> items = new ArrayList<Item>();
    Item item;
    for (int i = 0; i < 42; i++) {
        item = new Item();
        item.setDay(String.valueOf(i + 1));
        items.add(item);
    }

    List<String> yoteis = new ArrayList<String>();
    yoteis.add("Go to beach");
    items.get(15).setYotei(yoteis);

    final MonthCalendarAdapter adapter = new MonthCalendarAdapter(this, items); 
    calendar.setAdapter(adapter);

    calendar.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int pos,
                long id) {
            Toast.makeText(MonthCalendarActivity.this, "" + pos, Toast.LENGTH_SHORT).show();    
            List<String> newYoteis = new ArrayList<String>();
            newYoteis.add("new yotei");             
            items.get(pos).setYotei(newYoteis);
            adapter.notifyDataSetChanged();
        }

    });
}
@覆盖
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u month\u calendar);
GridView日历=(GridView)findViewById(R.id.month\u视图);
最终列表项=新的ArrayList();
项目;
对于(int i=0;i<42;i++){
项目=新项目();
设置日(字符串值为(i+1));
项目。添加(项目);
}
List yoteis=new ArrayList();
添加(“去海滩”);
项目。获取(15)。setYotei(yoteis);
最终MonthCalendarAdapter=新MonthCalendarAdapter(此,项);
calendar.setAdapter(适配器);
calendar.setOnItemClickListener(新的OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父级、视图、int pos、,
长id){
Toast.makeText(MonthCalendarActivity.this,“+pos,Toast.LENGTH_SHORT.show();
List newYoteis=newarraylist();
newYoteis.添加(“new yotei”);
items.get(pos.setYotei(newYoteis);
adapter.notifyDataSetChanged();
}
});
}
适配器:

List<Item> items;
Context mContext;
public MonthCalendarAdapter(Context context,
        List<Item> objects) {
    super(context, 0, objects);
    mContext = context;
    items = objects;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    MonthCell cell;
    LayoutParams params = new GridView.LayoutParams(65,80);
    if(convertView == null) {
        cell = new MonthCell(mContext, items.get(position));
        cell.setLayoutParams(params);
        cell.setScaleType(ImageView.ScaleType.CENTER_CROP);
    }else {
        convertView.setLayoutParams(params);
        cell = (MonthCell) convertView;
    }

    return cell;
}   
列表项;
语境;
公共MonthCalendarAdapter(上下文,
列出对象){
超级(上下文,0,对象);
mContext=上下文;
项目=对象;
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
蒙氏细胞;
LayoutParams params=新的GridView.LayoutParams(65,80);
if(convertView==null){
cell=newmonthcell(mContext,items.get(position));
cell.setLayoutParams(params);
cell.setScaleType(ImageView.ScaleType.CENTER\U裁剪);
}否则{
convertView.setLayoutParams(参数);
单元格=(MonthCell)convertView;
}
返回单元;
}   
蒙斯凯尔班:

public class MonthCell extends ImageView {

    Paint paint;
    Item item;
    public MonthCell(Context context) {
        super(context);
        paint = new Paint();
    }

    public MonthCell(Context context, Item item) {
        this(context);      
        this.item = item;

    }   

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.rgb(0, 176, 240));
        canvas.drawText(item.getDay(), 10, 20, paint);

        List<String> yoteis = item.getYotei();
        if(yoteis != null) {
            if(!yoteis.isEmpty()) {
                setBackgroundResource(R.drawable.cell);

                paint.setColor(Color.rgb(255, 124, 128));
                for(int i = 0; i < yoteis.size(); i++) {
                    canvas.drawText(yoteis.get(i), 10, 20 * (i + 2), paint);
                }
            }
        }
    }   
}
公共类MonthCell扩展了ImageView{
油漆;
项目;
公共MonthCell(上下文){
超级(上下文);
油漆=新油漆();
}
公共MonthCell(上下文,项){
这(上下文);
this.item=项目;
}   
@凌驾
受保护的void onDraw(画布){
super.onDraw(帆布);
绘制.setColor(Color.rgb(0176240));
drawText(item.getDay(),10,20,paint);
List yoteis=item.getYotei();
if(yoteis!=null){
如果(!yoteis.isEmpty()){
挫折资源(R.drawable.cell);
paint.setColor(Color.rgb(255、124、128));
对于(int i=0;i
第一次加载活动时,屏幕如下所示:

   if(convertView == null) {
       convertView = new MonthCell(mContext, null);
       ((MonthCell)convertView).setLayoutParams(params);
       ((MonthCell)convertView).setScaleType(ImageView.ScaleType.CENTER_CROP);
    }
    ((MonthCell)convertView).setItem(items.get(position));
1234567

8910

但当我点击日历时,顺序改变如下:

   if(convertView == null) {
       convertView = new MonthCell(mContext, null);
       ((MonthCell)convertView).setLayoutParams(params);
       ((MonthCell)convertView).setScaleType(ImageView.ScaleType.CENTER_CROP);
    }
    ((MonthCell)convertView).setItem(items.get(position));
42 41 40 39

7654321

(抱歉,我无法上传图像,因为我没有足够的声誉) 谁能向我解释一下为什么会发生这种情况以及如何解决它。
提前谢谢

我认为这是由于convertView的使用不正确造成的。使用下面的getView代码可以很容易地验证这个假设

public View getView(int position, View convertView, ViewGroup parent) {
  MonthCell cell;
  LayoutParams params = new GridView.LayoutParams(65,80);
  cell = new MonthCell(mContext, items.get(position));
  cell.setLayoutParams(params);
  cell.setScaleType(ImageView.ScaleType.CENTER_CROP);
  return cell;
}

您不能假设请求“位置”时传递的convertView包含“位置”处的项。您必须再次正确初始化convertView

我认为问题发生在这里

   if(convertView == null) {
    cell = new MonthCell(mContext, items.get(position));
    cell.setLayoutParams(params);
    cell.setScaleType(ImageView.ScaleType.CENTER_CROP);
}else {
    convertView.setLayoutParams(params);
    cell = (MonthCell) convertView;
}
尝试这样修改:

   if(convertView == null) {
       convertView = new MonthCell(mContext, null);
       ((MonthCell)convertView).setLayoutParams(params);
       ((MonthCell)convertView).setScaleType(ImageView.ScaleType.CENTER_CROP);
    }
    ((MonthCell)convertView).setItem(items.get(position));

此外,在customview
MonthCell
中,您应该为字段
项生成getter

谢谢您的回答。我使用了你的代码,它工作正常。但我想知道,在我的情况下,没有办法使用convertView?出于性能原因,您应该使用convertView。但您必须正确初始化它。您的代码以某种方式假设,当调用getView(position,convertView,…)时,convertView包含items.get(position)。这个假设是无效的,因此您必须重新初始化convertView并设置正确的项。jaredzhang先生的建议似乎是使用convertView的一个很好的理想方法,但它仍然不起作用。您能建议我如何正确初始化convertView吗?添加((MonthCell)convertView).setItem(items.get(position));对我来说似乎是正确的。(并删除公共MonthCell(上下文,Item-Item)构造函数并添加一个MontCell.setItem(Item-Item){this.Item=Item;}函数)我试图使用convertView,通过使用您的代码,顺序没有更改,但items.get(position)似乎没有正确获取。当我点击一个项目时,点击了一个单元格,另一个单元格的背景已经改变。我认为,正如@Marc Van Daele先生所说,“您不能假设请求‘位置’时传递的convertView包含‘位置’处的项。”