数据更改后,GridView不会刷新视图

时间:2014-07-21 20:31:45

标签: android gridview android-arrayadapter

我有一个带有自定义适配器的GridView,它不会刷新。

在调试器中,我可以看到getView之后没有调用notifyDataSetChanged。 我不明白为什么......我可以看到基础数据正在被改变,但GridView没有发生任何事情。

我尝试了几种不起作用的解决方案,所以我发布了我认为应该是正确的解决方案(即使它显然不是......)

这是我的主要活动

private GridView grid;

private TileGridAdapter gridAdapter;
private ArrayList<Tile> list;
private GameManager gameManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    gameManager = new GameManager(4);

    list = (ArrayList<Tile>) gameManager.getTiles();

    grid = (GridView) findViewById(R.id.grid);

    gridAdapter = new TileGridAdapter(this, list);
    grid.setAdapter(gridAdapter);

    grid.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
        public void onSwipeTop() {
            gameManager.move(Direction.Up);
            list.clear();
            list.addAll(gameManager.getTiles());
            gridAdapter.notifyDataSetChanged();
        }

        public void onSwipeRight() {
            Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
        }

        public void onSwipeLeft() {
            Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
        }

        public void onSwipeBottom() {
            Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
        }
    });

}

自定义适配器

public class TileGridAdapter extends ArrayAdapter<Tile> {

    Context context;
    ArrayList<Tile> tiles;

    public TileGridAdapter(Context context, ArrayList<Tile> tiles) {
        super(context, R.layout.cell_layout, tiles);

        this.context = context;
        this.tiles = tiles;
    }       

    @Override
    public int getCount() {
        return tiles.size();
    }

    @Override
    public Tile getItem(int position) {
        return tiles.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = convertView;

        if (view == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            view = inflater.inflate(R.layout.cell_layout, parent, false);

            Tile tile = tiles.get(position);

            TextView tv = (TextView) view.findViewById(R.id.cell_view);
            if (tile != null) {
                tv.setText(String.valueOf(tile.getValue()));
            }
        }

        return view;
    }
}

2 个答案:

答案 0 :(得分:0)

  1. 从您发布的代码中,无需覆盖getCount()getItem()方法。只需getView()即可。
  2. 您无法更新外部磁贴列表(在活动中)并期望适配器更新。这有很多原因。基本上它归结为您的外部列表不保证在适配器中是相同的列表引用。可以在这里阅读更多相关信息:ArrayAdapter Constructor - Issues
  3. 如果您需要将项添加到gridAdapter,请直接使用它的addAll()方法。如果您需要清除适配器中的项目...请使用clear()方法。

答案 1 :(得分:0)

据我所知,问题是如果convertview为null,则getView只会膨胀并填充视图。根据我的经验,convertview在列表的初始加载时仅为null,从那时起重新使用视图。您应该检查视图是否存在并且具有正确的数据。如果它有错误的数据,则填充新数据(或者只是总是填充新数据。)

这就是viewholder pattern可能有用的原因。

例如:

if( view == null || ((Holder)view.getTag()).getItem().equals(getItem()) ) 
{
    ...

你应该把检查分成多行,但这就是想法。



将除通货膨胀之外的所有内容移至if语句的外部。