0

So I'm attempting to create background task that needs to be run every hour in an Android app. Its a rather heavy task that takes around 5 - 10 minutes to finish, and right now it runs on the UI thread which of course isn't good, because it hangs the whole application. I've attempted the following in my MainActivity onCreate:

new Thread(new Runnable() {

    private Handler HeavyTaskHandler = new Handler(Looper.getMainLooper());

    public void run(){
        final TextView updatedTxt = findViewById(R.id.txt);
        updatedTxt.post(new Runnable() {
            @Override
            public void run() {
                updatedTxt.setText("Performing cleanup..");
            }
        });

        HeavyTask(); // <-- This method runs for 5 - 10 minutes

        updatedTxt.post(new Runnable() {
            @Override
            public void run() {
                updatedTxt.setText("Done..");
            }
        });

        HeavyTaskHandler.postDelayed(this, HeavyTaskCycle);
    }
}).start();

I have two issues with the above

  • It works fine the first time, and the task is performed in the background well without hanging the UI thread. However, after this first time and the next time(s) it is run, the UI thread hangs again when it is run. What am I missing?
  • Notice that before the HeavyTask() method is called i try to set a TextViews text to "Performing cleanup.." .. This never shows, only the "Done.." which happens after the HeavyTask() method is done. How can i ensure that the message also appears before?
Daniel Jørgensen
  • 1,183
  • 2
  • 19
  • 42
  • If your background task actually takes that long, it should probably be a [service](https://developer.android.com/guide/components/services). Do take into account if the user leaves your app during the operation. Unclear how you are "running" your code the second time through. You should include logcat of crash. – Morrison Chang May 30 '20 at 12:11
  • It doesnt crash it just hangs .. The `HeavyTaskHandler.postDelayed` is "scheduling" the code to run again every `HeavyTaskCycle` which works, but it hangs the UI thread. Not the first time though – Daniel Jørgensen May 30 '20 at 12:29
  • You are calling `postDelayed(...)` within your runnable and its on the `Looper.getMainLooper()` thread. See: [how to use postDelayed() correctly in android studio?](https://stackoverflow.com/q/42379301/295004) If you are trying to do scheduled work (i.e. database update) you should look at [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) – Morrison Chang May 30 '20 at 13:15

1 Answers1

0

I ended up doing the following from MainActivity which doesn't hang the application

private void CreateCleanUpThread()
{
    CleanUpThread = new Thread(new Runnable() {

        public void run(){
            try {
                while(true) {
                    performingCleanup = true;
                    final TextView updatedTxt = findViewById(R.id.updated_txt);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            updatedTxt.setText("Performing database history cleanup..");
                        }
                    });

                    HeavyTask(); // <-- This method runs for 5 - 10 minutes

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            updatedTxt.setText("Done..");
                        }
                    });
                    performingCleanup = false;
                    Thread.sleep(CleanUpCycle); // 1 hour wait time
                }
            } catch(Exception ex) {
                System.out.println("Error in CreateCleanUpThread : " + ex.getMessage());
            }
        }
    });
}

// onCreate in MainActivity
...
CleanUpThread.start();

Certainly not the best way, but it works and will do for now. Should be moved to a service instead i think.

Daniel Jørgensen
  • 1,183
  • 2
  • 19
  • 42