Android Run A Function In a Class In New Thread

12,536

Solution 1

I would suggest you use an AsyncTask. Its purpose matches exactly what you are trying to do. It allows you to run a background operation, and then update the UI with the result from such operation.

Solution 2

Your answer: As the other answers suggest, you should use thread.start() instead tmp.run().

The following description does not relate to your question directly, but it helps you to write better code, and protect you from errors that you will face in the future.

But for writing better code my suggestion is using handler. By using handler you can execute your operations in the main thread.

Eg: To update the value of a textView from a class that you created for other purposes, you have to post this operation (updating textView) to main thread, because your custom thread don't have permission to manipulate views.

Using handler in your project:

1.You should make an instance from the Handler class in your main thread:

public static Handler handler = new Handler();

2.From the second thread use that handler like this:

YourMainThreadClass.handler.post(new Runnable() {
    @Override
    public void run() {
        // Do Whatever
    }
});

Exception: You don't have to use handler for progressBar, but you should use handler for manipulating other views in the same issues. ProgressBar just an exception but I advise you to use handler in this case also.

Solution 3

You should start the Thread with thread.start() instead of calling run manually.

Thread thread = new Thread(tmp);
thread.start();

Solution 4

You could use an AsyncTask. This will make it much easier. You can pass the percentage using publishProgress, and update the UI in onProgressChange, which is automatically called on the UI thread.

To use an AsyncTask, we create an inner class, like the one below. You place any long running code within the doInBackgroun() method. This is automatically called on a background thread-- so your UI won't freeze.

When you want to update the UI, you can place your code inside onPreExecute() onPostExecute and onPublishProgress.

In your case, you can place the calls to the ProgressBar within the onPublishProgress method.

private class MyTask extends AsyncTask<Void, Integer, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        // Do Whatever
        // Each time you want the progress bar to update, you
        // call the publishProgress method, and pass the value
        // to be passed to the progressBar.setProgress method
        publishProgress(yourPercentage);

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        // update the progress bar. The value you pass in publishProgress
        // is passed in the values parameter of this method
        progressBar.setProgress(values[0]);
        super.onProgressUpdate(values);
    }


}
Share:
12,536
Admin
Author by

Admin

Updated on June 23, 2022

Comments

  • Admin
    Admin almost 2 years

    I have this code:

    MyClass tmp = new MyClass();
    tmp.setParam1(1);
    tmp.SetParam2("Test");
    tmp.setParam3("Test");
    ...
    

    Then I have

    tmp.heavyCalc();
    

    During this heavy calc operation I have to update progress bar in UI and show user that it's working with update in progress bar and some text to display. Now it doesn't work, because I'm not using thread, app becomes stuck and hanged, then suddenly returns that progressbar is 100% and all text all together appears suddenly.

    So I decided to make my function to run as new Thread. Inside definition of my class, I added implements Runnable So

    public class MyClass implements Runnable{
    

    Then I put that heavyCalc() function to be called new Run() function I created:

    @Override
    public void Run()
    {
    heavyCalc();
    }
    

    Now I do this:

    Thread thread = new Thread(tmp);
    tmp.run();
    

    It works, but still no change at all in UI, app becomes stuck, then suddenly progressbar 100% and app returns. What I'm missing?

  • kupsef
    kupsef almost 10 years
    I guess it does. Why?
  • Anubian Noob
    Anubian Noob almost 10 years
    When you call thread.run() you're just calling the method from the current thread. thread.start() creates a new thread and calls run() on that.
  • kupsef
    kupsef almost 10 years
    start() should be called on the thread, not on the runnable. Look at my answer.
  • Anubian Noob
    Anubian Noob almost 10 years
    OP's answer had tmp.run() which is why it didn't work. I edited my original comment...
  • kupsef
    kupsef almost 10 years
    Ohh I guess we misunderstood each other.
  • Admin
    Admin almost 10 years
    Now I get exception on place I try to update ProgressBar: "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
  • Admin
    Admin almost 10 years
    Can you tell me with psuedo code like my code, what should I change to make it AsyncTask?
  • user184994
    user184994 almost 10 years
    You need to make sure any calls to the progress bar are done so on the UI thread-- this is why you should try using an AsyncTask.
  • kupsef
    kupsef almost 10 years
    Yeah you have to update your view from the main thread. Consider using AsyncTask as Emmanuel suggested.
  • Admin
    Admin almost 10 years
    I did AsyncTask, but now I get: "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
  • user184994
    user184994 almost 10 years
    Make sure you're not updating the progress bar within the doInBackground method
  • Emmanuel
    Emmanuel almost 10 years
    You need to update the View components from onPostExecute(), onPreExecute(), or onProgressUpdate(). You cannot touch the UI Thread from doInBackground().
  • Admin
    Admin almost 10 years
    it says I should remove Override from OnPostExecute and OnPreExecute, I removed it, now how can I fire these events so often during process to update info on UI
  • Emmanuel
    Emmanuel almost 10 years
    Those methods are called by the system, you do not need to call them yourself. Please read the link above about AsyncTask.