我正在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开发的新手。
答案 0 :(得分:2)
a)我很确定你在设置之后不需要使TextView失效; Android应该自动执行此操作。
b)理论上,您将TextView
引用设置为成员变量,然后在onPostExecute
中引用它们,而不是将它们传递给doInBackground
。 doInBackground
反过来会使用任何数据位来计算新分数。您在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);
}
});
答案 1 :(得分:0)
您可以在TextView
的构造函数中传递AsyncTask
并从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