GridView does not update after data change

I have a GridView with a custom adapter that is not updating.

In the debugger, I see that getView not called after notifyDataSetChanged . I have no idea why ... I can see that the underlying data is changing, but nothing is happening with the GridView.

I tried several solutions that did not work, so I am posting what in my opinion should be correct (although this is clearly not ...)

This is in my main activity

 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(); } }); } 

And custom adapter

 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
source share
2 answers

As far as I can see, the problem is that your getView only inflates and fills the view if convertview is null. In my experience, convertview is null only when you first load the list, and then reuse the views. You must check if the view exists and if the relevant data is available. If it has incorrect data, it is filled with new data (or simply always filled with new data.)

This is why a viewer template can be useful.

For instance:

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

You should probably break this check into several lines, but this is an idea.


OR


Move everything except inflation outside the if statement.

0
source
  • From your published code, there is no need to override the getCount() and getItem() methods. Just getView() will work fine.
  • You cannot update the external style list (in action) and wait for the adapter to update. This is bad for many reasons. Basically it comes down to your external list, it is not guaranteed that it will be a link to the list in the adapter. Read more here: ArrayAdapter Constructor - Problems
  • If you need to add elements to the gridAdapter, use the addAll() method directly. If you need to clean the elements from the adapter ... use its clear() .
0
source

Source: https://habr.com/ru/post/1261832/


All Articles