Question

I've searched the internet far and wide about getting the UI to update in real-time in Android to no avail. I implemented an AysncTask class as most of the other posts suggested, but it's still not updating my UI in real-time like I want. It only updates after the program is done running. I've even been getting the "Skipped n frames. The application may be doing too much work in its main thread." error, which I don't understand because I'm trying to do these updates in the UI thread. About 5 seconds into running my program the screen turns black and stays like that until its done finishing. Any help would be much appreciated as I've been pulling my hair out on this one for awhile Here's my code.

EDIT: Solved. Removed the Thread.sleep(n) from my UI thread and added it to my AsyncTask. Thanks everyone!

Main class:

public class Home extends Activity {
// Declare objects
Button turingB, socratesB, voltaireB, descartesB, platoB;
int[] eating, thinking, hungry;
Philosopher socrates, turing, voltaire, descartes, plato;
Philosopher[] philosophers;
Chopstick[] chopsticks;
TextView info;
String value;
Context context;
int toastLength;
boolean turingHungry, socratesHungry, voltaireHungry, descartesHungry, platoHungry;
String running;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    // Instantiate objects (keep track of each button individually
    context = getApplicationContext();
    toastLength = Toast.LENGTH_SHORT;
    info = (TextView) findViewById(R.id.textView1);
    info.setText("Click Start to begin!");
    socratesB = (Button) findViewById(R.id.button1);
    descartesB = (Button) findViewById(R.id.button5);
    platoB = (Button) findViewById(R.id.button4);
    voltaireB = (Button) findViewById(R.id.button3);
    turingB = (Button) findViewById(R.id.button2);
    running = "false";

    // Set all philosophers to thinking (blue)
    //      socratesB.setBackgroundColor(Color.BLUE);
    //      descartesB.setBackgroundColor(Color.BLUE);
    //      platoB.setBackgroundColor(Color.BLUE);
    //      voltaireB.setBackgroundColor(Color.BLUE);
    //      turingB.setBackgroundColor(Color.BLUE);
    turingHungry = false;
    socratesHungry = false;
    voltaireHungry = false;
    descartesHungry = false;
    platoHungry = false;

    //Button platoTempButton = (Button) findViewById(R.id.button4);
    // Listen for buttons
    OnClickListener pBtn = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            platoHungry = true;
        }
    };
    //platoTempButton.setOnClickListener(pBtn);

    OnClickListener tBtn = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            turingHungry = true;
        }
    };
    OnClickListener sBtn = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            socratesHungry = true;
        }
    };
    OnClickListener vBtn = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            voltaireHungry = true;
        }
    };
    OnClickListener dBtn = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            descartesHungry = true;
        }
    };
    platoB.setOnClickListener(pBtn);
    turingB.setOnClickListener(tBtn);
    socratesB.setOnClickListener(sBtn);
    voltaireB.setOnClickListener(vBtn);
    descartesB.setOnClickListener(dBtn);

    // Set arrays to count time spent eating, thinking, hungry
    eating = new int[5];
    thinking = new int[5];
    hungry = new int[5];

    // Create the chopsticks
    chopsticks = new Chopstick[5];
    for (int i = 0; i < 5; i ++)
    {
        chopsticks[i] = new Chopstick(i);
    }
    for (Chopstick chop: chopsticks)
    {
        chop.available = true;
    }

    // Create the philosophers
    philosophers = new Philosopher[5];
    philosophers[0] = new Philosopher(0, chopsticks[0], chopsticks[1], "Plato", platoB);
    philosophers[1] = new Philosopher(1, chopsticks[1], chopsticks[2], "Turing", turingB);
    philosophers[2] = new Philosopher(2, chopsticks[2], chopsticks[3], "Socrates", socratesB);
    philosophers[3] = new Philosopher(3, chopsticks[3], chopsticks[4], "Voltaire", voltaireB);
    philosophers[4] = new Philosopher(4, chopsticks[4], chopsticks[0], "Descartes", descartesB);    

    // Get sim time from user
    AlertDialog.Builder alert = new AlertDialog.Builder(this);
    alert.setTitle("Simulation Time");
    alert.setMessage("Please length of time for the simulation to run (in seconds)");
    final EditText input = new EditText(this);
    alert.setView(input);
    alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            value = String.valueOf(input.getText());
        }
    });
    alert.show();

    // Get info
    Bundle extras = getIntent().getExtras();
    if (extras != null)
    {
        running = extras.getString("runApp");
        value = extras.getString("numToRun");
    }
    // Run app
    if (running.equals("true"))
    {
        System.out.println("RUNNING!!!");
        run(value);
    }
}

public void run(String length)
{
    int num = Integer.parseInt(length);
    // Run num times
    for (int i = 0; i < num; i++)
    {
        try {
            // Pass current index, and data arrays to step method
            step(i, eating, thinking, hungry);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // Print out some data
    for (int j = 0; j < 5; j++)
    {
        System.out.println("Philosopher " + j + " ate: " + eating[j]);
        System.out.println("Philosopher " + j + " thought: " + thinking[j]);
        System.out.println("Philosopher " + j + " was hungry: " + hungry[j]);
    }
    running = "false";
}

// Run simulation n times (n specified by the user) 
public void startSim(View v)
{
    Intent my_intent = new Intent(this, Home.class);
    my_intent.putExtra("runApp", "true");
    my_intent.putExtra("numToRun", value);
    startActivity(my_intent);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.home, menu);
    return true;
}
// Reset simulation
public void reset(View v)
{
    Intent my_intent = new Intent(this, Home.class);
    startActivity(my_intent);
}

// Return hunger status of philosopher
public boolean isHungry(String name) {
    if (name.equals("Voltaire"))
        return voltaireHungry;
    else if (name.equals("Socrates"))
        return socratesHungry;
    else if (name.equals("Plato"))
        return platoHungry;
    else if (name.equals("Turing"))
        return turingHungry;
    else if (name.equals("Descartes"))
        return descartesHungry;
    else
        return false;
}

// Step method for simulation
// Takes the current index and each of the data arrays
public void step(int i, int[] eating, int[] thinking, int[] hungry) throws InterruptedException
{
    // Make random number
    Random randomGenerator = new Random();
    int num = randomGenerator.nextInt(10);

    // Randomly set a philosopher isFull to false (hungry) (10% chance for each to become hungry if not specified by the user)
    if (isHungry(philosophers[0].name))
        philosophers[0].isFull = false;
    if (num == 1 || isHungry(philosophers[1].name))
        philosophers[1].isFull = false;
    if (num == 2 || isHungry(philosophers[2].name))
        philosophers[2].isFull = false;
    if (num == 3 || isHungry(philosophers[3].name))
        philosophers[3].isFull = false;
    if (num == 4 || isHungry(philosophers[4].name))
        philosophers[4].isFull = false;


    // For each philosopher
    for (Philosopher phil: philosophers)
    {
        // Print current info
        System.out.println("PHIL: " + phil.name + " NUM: " + num + " RIGHT: " + phil.rightChopstick.available + " LEFT: " + phil.leftChopstick.available);
        // Temp id var
        int tempId = phil.id;

        // If philosopher is hungry, try to eat
        if (phil.isFull == false)
        {
            // Try to eat only if both chopsticks are available
            if (phil.rightChopstick.pickUp(phil.name) && phil.leftChopstick.pickUp(phil.name))
            {
                // Change button color
                new Background(phil.button).execute((long) 1);
                //Toast.makeText(context, phil.name + " is eating.", toastLength).show();
                // Increment time spent eating
                eating[tempId]++;                           
            }
            // Check to see if the philosopher is already eating (has both chopsticks)
            else if (phil.rightChopstick.who.equals(phil.name) && phil.leftChopstick.who.equals(phil.name))
            {
                //Toast.makeText(context, phil.name + " is eating.", toastLength).show();
                new Background(phil.button).execute((long) 1);
                // Increment eating
                eating[tempId]++;
                // 30% chance to stop eating
                if (num >= 5 && num <=7)
                {
                    // Put down chopsticks
                    phil.rightChopstick.putDown();
                    phil.leftChopstick.putDown();
                    // Stop eating
                    phil.isFull = true;
                }
            }
            // Hungry
            else
            {
                // Change button color
                new Background(phil.button).execute((long) 3);
                //Toast.makeText(context, phil.name + " is hungry.", toastLength).show();

                // Increment time spent hungry
                hungry[tempId]++;                       
            }
        }               
        // Thinking
        else
        {
            new Background(phil.button).execute((long) 2);
            //Toast.makeText(context, phil.name + " is thinking.", toastLength).show();
            // Increment time spent thinking
            thinking[tempId]++;
        }
        Thread.sleep(1000);
    }           
    // Make each step count as 1 second (1000 miliseconds)
    System.out.println("--------------------------------------------------------------");
    Thread.sleep(5000);
}

}

Background class (AsyncTask):

public class Background extends AsyncTask<Long, Void, Void> 
{
// Variables
String color;
Button button;

public Background(Button button)
{
    this.button = button;
}

@Override
protected Void doInBackground(Long... params) {    
    // Get which color the button needs to be
    try
    {
        // Change the color based on the value passed in
        if (params[0] == 3)
        {
            color = "RED";
        }
        else if (params[0] == 2)
        {
            color = "BLUE";
        }
        else if (params[0] == 1)
        {
            color = "GREEN";
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    return null;
}

@Override
protected void onPostExecute(Void result) {
    // Set button to that color
    System.out.println("Updating color in real time...");
    button.setBackgroundColor(Color.parseColor(color));

}

@Override
protected void onPreExecute() {
}

@Override
protected void onProgressUpdate(Void... values) {

}

}

Was it helpful?

Solution

Here is one problem

Thread.sleep(1000);

and here is another

Thread.sleep(5000);

these are both making the UI sleep for a total of 6 seconds. You almost never want to call sleep() on the UI Thread. You can do this in doInBackground() or anywhere else that runs on a background Thread.

Edit

You don't set your Listeners. For example:

platoB.setOnClickListener(new pBtn());

OTHER TIPS

Progress can be set with publishProgress in your asynctask, you get a call to onProgressUpdate in the UI thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top