我正在尝试在循环处理时更新文本视图。这是我用于此活动的代码。
public class StartDayActivity extends Activity {
Data data_;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.startdayscreen);
Thread seperationTimer = new Thread(){
public void run(){
int seperationTimer = 5000;
int weatherAffect = 0;
int randomEventAffect = 0;
int locationTotalAvailable = 10;
//int servingTime = 3000;
int totalAvailableCustomers = (weatherAffect + randomEventAffect + locationTotalAvailable);
int dayTimer = (totalAvailableCustomers * seperationTimer);
int seperationTimerDay = 0;
int lemonadeSold = 11;
int totalDrinksSold = 0;
int pitcherSize = 12;
int totalLemonsUsed= 0;
int totalIceUsed =0;
int totalSugarUsed = 0;
int totalCupsUsed = 0;
double drinkPrice = 0.80;
try{
while(seperationTimerDay < dayTimer){
sleep(seperationTimer);
seperationTimerDay = seperationTimerDay + seperationTimer;
lemonadeSold = lemonadeSold + 1;
totalDrinksSold += 1;
data_.cups_ -= 1;
totalIceUsed += 2;
if(lemonadeSold == pitcherSize){
lemonadeSold = 0;
data_.lemons_ -= 4;
data_.sugar_ -= 2;
totalSugarUsed +=2;
totalLemonsUsed +=4;
}
if(data_.lemons_ == 0 || data_.ice_ == 0 || data_.sugar_ ==0 || data_.cups_ == 0){
break;
}
updateView();
Log.d("TAG", "for each : " + data_.ice_);
//calcMarketing();
}
data_.day_gross_profit_ = (totalDrinksSold * drinkPrice);
data_.cash_ += (totalDrinksSold * drinkPrice);
Intent i = new Intent("com.game.lemonade.PLAYSCREEN");
startActivity(i);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
finally{
finish();
}
}
};
seperationTimer.start();
}
@Override
public void onStart(){
super.onStart();
data_ = getData();
}
@Override
public void onResume(){
super.onResume();
data_ = getData();
//refreshDisplay();
}
@Override
public void onPause(){
super.onPause();
saveData();
//refreshDisplay();
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
//refreshDisplay();
}
private Data getData() {
GameData player_data = new GameData(this);
player_data.open();
Data game_state = new Data(player_data.getGameString());
player_data.close();
return game_state;
}
private void saveData() {
GameData player_data = new GameData(this);
player_data.open();
player_data.setGameString(data_.SerializeGame());
player_data.close();
}
private void updateView(){
((TextView)findViewById(R.id.lemonsLeftText2)).setText(
(data_.lemons_) );
}
}
有没有更好的方法来尝试这样做?我怎么会这样做?我执行updateView()
尝试更新textview时出错。
答案 0 :(得分:1)
错误消息已包含您问题的答案。您无法从不同的线程更新UI - 使用runOnUIThread()
执行此操作。为了电池的缘故 - 在onCreate()中引用textView并重用它。
答案 1 :(得分:0)
您无法直接使用线程访问UI。请使用AsyncTask
或Handler
进行影响用户界面的较长线程操作。
检查这些;
http://developer.android.com/resources/articles/painless-threading.html
http://developer.android.com/reference/android/os/Handler.html
答案 2 :(得分:0)
不允许您从任何非主线程的线程更改View
的外观。
@Serdar对如何处理它有一些很好的建议。
每次你需要调用setText()时,你应该避免调用findViewById()。就系统资源而言,findViewById()是一个相当昂贵的调用。您的应用运行效果越好,就越少。
我建议你自己创建一个TextView引用并在onCreate()中调用findViewById()并设置对它返回给你的引用。然后在你的updateView()方法中调用yourTxt.setText("");
答案 3 :(得分:0)
虽然其他答案已经涵盖了您的问题的答案,但我会在文档的这一部分指出。
特别是最后一部分。
此外,Andoid UI工具包不是线程安全的。因此,您不能从工作线程操纵UI - 您必须从UI线程对您的用户界面进行所有操作。因此,Android的单线程模型只有两个规则:
- 不要阻止UI线程
- 不要从UI线程外部访问Android UI工具包
确实有两个非常简单的规则,但如果坚持下去,你就会避免很多问题。
答案 4 :(得分:0)
您应该使用Handler
类:
你打电话的地方:
updateView();
替换为:
myHandler.sendEmptyMessage(0);
在处理程序中:
private Handler myHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==0){
updateView();
}
};
};