Robert H.
Robert H.

Reputation: 59

How to Properly Update TextViews in the UI in Android?

I am trying update text views while this loop is processing. Here is my code that I am using for this activity.

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

Is there a better way to try to do this? And how would I want to do that? I get an error when I do the updateView() to try to update textview.

Upvotes: 0

Views: 1357

Answers (5)

Serdar Dogruyol
Serdar Dogruyol

Reputation: 5157

You cant access the UI using threads directly.Either use an AsyncTask or Handler for your longer thread operations which effect the UI.

Check these;

http://developer.android.com/resources/articles/painless-threading.html

http://developer.android.com/reference/android/os/Handler.html

Upvotes: 0

ClarkXP
ClarkXP

Reputation: 1233

You should use Handler class:

Where you call:

    updateView();

replace with:

    myHandler.sendEmptyMessage(0);

In the handler:

    private Handler myHandler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if(msg.what==0){
            updateView();
        }
    };
};

Upvotes: 0

Squonk
Squonk

Reputation: 48871

Although the other answers have covered the answer to your question, I'll point you at this section in the documentation.

Threads

In particular the last part.

Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:

  • Do not block the UI thread
  • Do not access the Android UI toolkit from outside the UI thread

Two very simple rules indeed but if you stick to them you'll avoid a lot of problems.

Upvotes: 0

FoamyGuy
FoamyGuy

Reputation: 46856

You are not allowed to change the appearance of your Views from any thread that is not the main thread.

@Serdar has some great suggestions for how to handle that.

Also you should avoid calling findViewById() each time you need to call setText(). findViewById() is a fairly expensive call in terms of system resources. The fewer calls like that you make the better your app will run.

I suggest you make yourself a TextView reference and make your findViewById() call inside onCreate() and set your reference to what it returns to you. Then in your updateView() method call something like yourTxt.setText("");

Upvotes: 0

Konstantin Pribluda
Konstantin Pribluda

Reputation: 12367

Error message already contains answer to your question. You can not update UI from different thread - use runOnUIThread() to do this. And for battery sake - get reference to textView in onCreate() and reuse it.

Upvotes: 1

Related Questions