【问题标题】:Refresh Game Score TextView using AsyncTask使用 AsyncTask 刷新游戏分数 TextView
【发布时间】:2012-04-16 14:44:04
【问题描述】:

我正在 Android 中编写一个棋盘游戏,其中 UI 由用于得分的文本视图(CPUScore 和 PlayerScore)组成。我遇到的问题是,当调用 onCreate 时,UI 不会从其初始值更新分数。我看过类似的问题,最建议的解决方案是使用 AsyncTask 在后台更新 UI 线程。但是我没有找到明确处理如何在 AsyncTask 中使用 textViews 的解决方案。

这是我的尝试:

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

AsyncTask 子类:

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

     }

问题: 如何将我在 onCreate 方法中声明的 textViews 传输到 AsyncTask 方法?我难住了。我对Android开发相当陌生。

【问题讨论】:

  • 制作playerScoreForm等类成员/将它们传递到构造函数或自定义AsyncTask的参数中。
  • 你能给我一个粗略的例子吗?

标签: android user-interface textview android-asynctask updating


【解决方案1】:

a) 我很确定您在设置 TextView 后不需要使它们无效; Android 应该自动执行此操作。

b) 理论上,您可以将 TextView 引用设置为成员变量,然后在 onPostExecute 中引用它们,而不是将它们传递给 doInBackgrounddoInBackground 反过来将采用任何位数据使您能够计算新分数。您在doInBackground 上所做的是任何会导致计算新分数的操作。来自doInBackground 的返回值被传递到onPostExecute。然后,您将使用 onPostExecute 中的数据更新 TextView(现在是成员变量)。那有意义吗?您实际上还没有在此处发布任何可以更新这些分数值的代码。

请参阅here 以获取快速示例。

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

 }

编辑:如果你不想在 doInBackgroundThread 中做计算逻辑,你可能只想使用:

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

或者:

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

【讨论】:

  • 感谢您的评论。分数 public int PlayerTotal 和 public int CPUTotal 在玩游戏期间由游戏逻辑更新。我的问题是如何转换: TextView playerScoreForm = (TextView) findViewById(R.id.PlayerTotalScore); playerScoreForm.setText(Integer.toString(PlayerTotal));到 AsyncTask 进程。在 textView PlayerScoreForm 上执行 setText 时,PlayerTotal 的更新值(从游戏循环更新)不会传递到 UI 线程。
  • 听起来 AsyncTask 不适合在这里使用。我会更新我的答案。
  • 非常感谢。我使用了您的第一个编辑建议并将其包含在 void 方法 updateScores() 中: public void updateScores() { runOnUiThread(new Runnable() { @Override public void run() { playerScoreForm.setText(Integer.toString(PlayerTotal)); CPUScoreForm.setText(Integer.toString(CPUTotal)); } }); }。诀窍是从 onCreate 调用它以获得初始分数,然后从生成分数的游戏中的方法调用它。
【解决方案2】:

您可以在AsyncTask 的构造函数中传递TextView 并通过onPostExecute 方法对其进行更新

private class updatePlayerScore extends AsyncTask<Void, Void, Integer> {
private TextView view;
public updatePlayerScore(TextView textView){
this.view = textView;
}
        @Override
            protected Integer doInBackground(Void... params) {
            int score = 0; 

                    //do you calculation the 

             return score;
         }
         protected void onPostExecute(Integer result) {
           view.setText(Integer.toString(result));
         }

     }

注意:如果您的活动配置因任何原因发生更改,即用户旋转设备并且您 AsyncTask 尚未完成任务,您 TextView 的更新将不会更新,因此你应该保留你 AsyncTask 的一个实例并更新 TextView

【讨论】:

  • 感谢您的贡献。我的错误是我试图从 onCreate 中获取分数,但这是错误的,因为 onCreate 只会触发一次(即首次创建活动时),因此在执行 onCreate 时尝试在那里获取分数意味着分数保留了它们的初始值在初始化时传递给 onCreate。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多