Search code examples
androiduser-interfacetextviewandroid-asynctaskupdating

Refresh Game Score TextView using AsyncTask


I am writing a board game in Android where the UI consists of textViews for the scores (CPUScore and PlayerScore). The problem I have is that the UI does not update the score from its initial value when onCreate is called. I have looked at similar questions and the solution most suggested is to use AsyncTask to update the UI thread in the background. However I did not find a solution that dealt explicitly with how to use textViews in AsyncTask.

Here is my attempt:

@Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
//....
setContentView(R.layout.main_layout);

//.....
//------------ textViews declared here don't refresh -------------------
TextView playerScoreForm = (TextView) findViewById(R.id.PlayerTotalScore);
        playerScoreForm.setText(Integer.toString(PlayerTotal));
        playerScoreForm.invalidate();

        TextView CPUScoreForm = (TextView) findViewById(R.id.CPUTotalScore);
        CPUScoreForm.setText(Integer.toString(CPUTotal));
        CPUScoreForm.invalidate();
//--------------------------------------------------------------------------    
//AsyncTask method:    
        new updatePlayerScore().execute(PlayerTotal);
        new updateCPUScore().execute(CPUScoreForm);
    }

The AsyncTask subclasses:

private class updatePlayerScore extends AsyncTask<TextView, Void, Void> {

        @Override
            protected TextView doInBackground(TextView... params) {


                    // what to put here??



            }
             return playerScoreForm;
         }

            @Override
         protected void onProgressUpdate(Integer... values) {
             //??
         }

         protected void onPostExecute(Integer result) {
            playerScoreForm.setText(Integer.toString(result));
         }

     }


    private class UpdateCPUScore extends AsyncTask<TextView, Integer, Integer> {
        // same syntax as updatePlayerScore

     }

Question: how do I transfer the textViews that I declared in the onCreate method to the AsyncTask method? I am stumped. I am fairly new to Android development.


Solution

  • a) I'm pretty sure you shouldn't need to invalidate the TextViews after you set them; Android should do that automagically.

    b) In theory you'd set your TextView references to be member variables and then reference them in onPostExecute instead of passing them into doInBackground. doInBackground in turn will take whichever bits of data enable you to calculate the new score. What you would do on doInBackground is whatever action would cause a new score to be calculated. The return value from doInBackground gets passed into onPostExecute. You would then update the TextView (now a member variable) with this data in onPostExecute. Does that make sense? You haven't actually posted any code here that would update those score values.

    See here for a quick example.

    private TextView myScoreView;  //initialized in onCreate as you do above.
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        //....
        setContentView(R.layout.main_layout);
    
        //.....
    
        myScoreView = (TextView) findViewById(R.id.PlayerTotalScore);
        myScoreView.setText(Integer.toString(PlayerTotal));
    
        new updatePlayerScore().execute(1,2); //parameters for calculation
    }
    
    private class updatePlayerScore extends AsyncTask<Integer, Integer, Integer> {
    
            @Override
            protected TextView doInBackground(Integer... params) {
    
                    int score = params[0] + 2 * params[1];
                    return score;
            }
    
    
            @Override
            protected void onProgressUpdate(Integer... values) {
                //if you want to provide some indication in the UI that calculation 
                //is happening, like moving a progress bar, that's what you'd do here.
            }
    
            @Override
            protected void onPostExecute(Integer scoreCalculationResult) {
               myScoreView.setText(Integer.toString(scoreCalculationResult));
            }
    
     }
    

    Edit: If you don't want to do the calculation logic in doInBackgroundThread, you probably just want to use:

    runOnUiThread(new Runnable(){
         @Override
         public void run(){
             myScoreView.setText(PlayerScoreValue);
         }
    });
    

    Or:

     myScoreView.post(new Runnable(){
         @Override
         public void run(){
             myScoreView.setText(PlayerScoreValue);
         }
    });