Android Run A Function In a Class In New Thread
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);
}
}
Admin
Updated on June 23, 2022Comments
-
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 Runnabl
e Sopublic class MyClass implements Runnable{
Then I put that
heavyCalc()
function to be called newRun()
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 almost 10 yearsI guess it does. Why?
-
Anubian Noob almost 10 yearsWhen you call
thread.run()
you're just calling the method from the current thread.thread.start()
creates a new thread and callsrun()
on that. -
kupsef almost 10 yearsstart() should be called on the thread, not on the runnable. Look at my answer.
-
Anubian Noob almost 10 yearsOP's answer had
tmp.run()
which is why it didn't work. I edited my original comment... -
kupsef almost 10 yearsOhh I guess we misunderstood each other.
-
Admin almost 10 yearsNow 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 almost 10 yearsCan you tell me with psuedo code like my code, what should I change to make it AsyncTask?
-
user184994 almost 10 yearsYou 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 almost 10 yearsYeah you have to update your view from the main thread. Consider using AsyncTask as Emmanuel suggested.
-
Admin almost 10 yearsI did AsyncTask, but now I get: "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
-
user184994 almost 10 yearsMake sure you're not updating the progress bar within the
doInBackground
method -
Emmanuel almost 10 yearsYou need to update the
View
components fromonPostExecute()
,onPreExecute()
, oronProgressUpdate()
. You cannot touch the UIThread
fromdoInBackground()
. -
Admin almost 10 yearsit 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 almost 10 yearsThose methods are called by the system, you do not need to call them yourself. Please read the link above about
AsyncTask
.