'Thread freezes UI

I have this button that when clicked calls a thead to update user ui:

averageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            new Testing().execute();
        }
    });

The method gets executed but it freezes the UI for 10 seconds. I want to update the UI everytime I call the averageMiles.append(mile) method.

    class Testing extends AsyncTask<Void, Void, Void> {
    @Override
    protected void onPostExecute(Void unused) {

        int x = 0;
        while (true) {

            if (x == 10) {
                break;
            }

            ArrayList<Double> milesList = new ArrayList<>();


            if (x == 0) {
                averageMiles.setText("mph: ");
            }

            String mile = milesValue.getText().toString();
            if (!isNum(mile)) {
                continue;
            }

            averageMiles.append(mile);
            milesList.add(Double.valueOf(mile.trim()));
            x++;
            if (x == 10) {
                averageMiles.append("\nAverage: " + getAverage(milesList));
                return ;
            } else {
                averageMiles.append(", ");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }


    }


Solution 1:[1]

Use ThreadPool executor from official oracle and android developer documentations

Oracle Docs - java.util.concurrent.ThreadPoolExecutor
Android Docs - java.util.concurrent.ThreadPoolExecutor

as you have specified you are using java the above two documentation is recommended by google as show below for AsyncTask

This class was deprecated in API level 30. Use the standard java.util.concurrent or Kotlin concurrency utilities instead.

The ultimate objective is the android is saying that, if you want to update UI, simply use runOnUiThread with a new runnable you update the UI, which means for each UI update you may be creating fresh short term thread which only updates the UI and thread finishes and garbage collected

Sample Code

public class MainActivity extends AppCompatActivity {
    int count = 0;
    Executor ex;
    MyThread th;

    class MyThread extends Thread implements Runnable {
        private boolean running=false;

        public void setRunning(boolean running) {
            this.running = running;
        }

        @Override
        public void run() {
            while(running) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        count++;
                        TextView tv = findViewById(R.id.textView);
                        tv.setText(String.valueOf(count));
                    }
                });
            }
        }
    }

    public void onStartClick(View view) {
        th = new MyThread();
        ex = Executors.newSingleThreadExecutor();
        th.setRunning(true);
        ex.execute(th);
    }

    public void onStopClick(View view) {
        if(th!=null) {
            th.setRunning(false);
        }
    }
}

all the member variables of the class should be only accessed inside runOnUiThread, for example count++ count is a variable of the MainActivity if you want any value specific to the thread you put only inside the MyThread class

Never try to access any of the MainActivity variable inside the run() method

You can also write MyThread as separate class, and set values similar to th.setRunning before starting the thread.

If you want a callback after the thread is completed use an interface which will give you a callback method in your MainActivity

So it is simply core java
I have created an example with interface
Concurrent Executor Interface Example

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1