0

I work on a Battleships game as my first Android application.

I decided to use a ViewSwitcher that holds two GridViews. One bUserGrid is for the User field (hosting user ships), bComputerGrid is for the Computer field (showing user shots).

GridView bComputerGrid, bUserGrid, mComputerGrid, mUserGrid;
ViewSwitcher bigSwitcher, miniSwitcher;

User strikes (taps Computer field).The application runs the AsyncTask userAttack which defines whether that strike was successful or not.

bComputerGrid.setOnItemClickListener(new OnItemClickListener() {
  public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    runUserAttack(position);
  }
});

If user missed, then in a onPostExecute() section of userAttack I call notifyDataSetChanged() in order to refresh the bComputerGrid.

    protected void onPostExecute(String message) {
        ...
        bComputerAdapter.notifyDataSetChanged();
        mComputerAdapter.notifyDataSetChanged();
        firstmateMsg.setText(message);
        mUserBundle = mUserAttack.getmUBundle();
        mUserAttack=null;
        if (isCancelled()) return;
        if (mUserBundle.getBoolean("userMissed")) {
            mComputerAttack = new computerAttack();
            mComputerAttack.execute(mComputerBundle);
        } else {
            if (doesWon(seqComputerShips)) {
                showDialog(0);
            }
        }
    }

But it doesn’t happen! Following statement doesn’t update bComputerGrid, if user misses.

bComputerAdapter.notifyDataSetChanged();

Then here in onPostExecute() section of userAttack I start AsyncTask computerAttack. In onPreExecute() section of computerAttack I switch bComputerGrid to bUserGrid by calling

bigSwitcher.showNext();

Switching happens but bComputerGrid hasn't been updated before that!

Computer does its strike and successfully refreshes the user field in onProgressUpdate() section of computerAttack by calling bUserAdapter.notifyDataSetChanged(). When Computer missed, the application comes to wait for the user strike (tap) again.

    protected void onProgressUpdate(String... messages) {
        ...
        mUserAdapter.notifyDataSetChanged();
        bUserAdapter.notifyDataSetChanged();

    }
    protected void onPostExecute(Boolean result) {
        mComputerBundle = mComputerAttack.getmCBundle();
        mComputerAttack=null;
        if (field_switch) {
            switchViews();
        }

    }

But why I can’t refresh bComputerGrid before that switching and Computer shot happens?

Could you, please, help me?

  • Are you sure that you don't invoke notifyDataSetChanged() before changing the underlying data of the adapter? Set breakpoint at bComputerAdapter.notifyDataSetChanged(); and see what happens. – Kiril Kirilov Jan 30 '11 at 15:13
  • Thanks for your attention, fiction! I set the breakpoint and sure that underlying array changes before I invoke notifyDataSetChanged(). – captaindan Jan 30 '11 at 16:13

1 Answers1

0

Where you update your adapters? You change underlying data of the adapter, or you change the adapter list? Adapters are also part of the UI, so changes of the adapter itself should happen only in a GUI thread. I got a couple of UI Exceptions (on display) telling me so in some other project as I changed the adapter contents in a Service Thread. Eventually you have to recreate your adapter list to reflect changes in underlying data?

Oliver
  • 1,269
  • 13
  • 21
  • Thanks for your attention, Oliver! I change underlying data of the adapters in onPostExecute() section just before notifyDataSetChanged() call. updateSeqComputerShips(int1D_to_int2D(mUserAttack.getmUBundle().getIntArray("computerShips"))); – captaindan Jan 30 '11 at 15:49