I am having a main class A, from which i create an object to class B extending Asynctask. Have set content view in A. Now in doInBackground of B, i want to update the textView of A, but its giving
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Exception. I tried declaring the setcontentview in B as well, but no use, can anyone please tell how to edit the textview of A in B??
override onProgressUpdate and call publishProgress in doInBackground
You need to call setText() from the UI thread, so either from onPreExecute(), onPostExecute() or in onProgressUpdate()
You could also use a runOnUiThread() handler in doInBackground(), but that kind of defeats the purpose of using an AsyncTask.
If the text update has to do with progress information, then you could use publishProgress()/onProgressUpdate() for that.
If it's not a progress update in a wider sense then I'm with Raghav -- you should consider another approach then.
We should not perform any ui changes in the doinBackgroud. You should and can perform in post execute. and also you can set notification in preexecute or onProgressUpdate.
Hope this will help you.
doInBackground is work thread. You have handle View in UI thread. please do it in onPreExecute(), onPostExecute() or onProgressUpdate. All these are working in UI Thread.
Of course you can pass Integer to onProgressUpdate. please notice the second paramters: AysncTask<Void, Integer, VOid>, the second parameter means the onProgressUpdate parameter type
Related
why should we use onProgressUpdate() method in Asynctask class,
i am using onPreExecute() and onPostExecute() along with doInBackground() but never used onProgressUpdate,In which cases we will use this method.
Thanks in Advance for your response.
onProgressUpdate(Progress...), invoked on the UI thread after a call
to publishProgress(Progress...). The timing of the execution is
undefined. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
As you read, you can publish your async task progress by using this.
protected void onProgressUpdate(Integer... progress) {
showProgressPercent(progress[0]);//write your own codes
}
Source
onProgressUpdate() is used to better the user experience by updating the user about the background process initiated at some time. For more information, refer to the docs.
AsyncTask lifecycle : onPreExecute -> doInBackground -> onPostExecute
onPreExecute is calling on MainThread. which means you can touch views.
doInBackground is calling on BackgroundThread. which means you can't touch views.
onPostExecute is calling on MainThread.
so while your job is going on inside doInBackground, you may want to notify user about job's progress but you can't notify user because it's calling on BackgroundThread. you need to jump to MainThread and AsyncTask provides you onProgressUpdate function to make it.
you can call publishProgress inside doInBackground.
I am using AsyncTask to upload data to UI. i wrote the code to download data from server in a separate method and i am calling that method from doinBackground. It will give error because UI methods can't access from doInBackground.but, i want to access . any alternative process is there to access the UI method from doinBackground.?
any alternative process is there to access the UI method from doinBackground.?
Call publishProgress() in doInBackground(). Put your UI-updating logic in onProgressUpdate() of your AsyncTask. onProgressUpdate() will be called on the main application thread (a.k.a., UI thread) after you call publishProgress(). Here is a sample project demonstrating this.
Call runOnUiThread(Runnable action)
more here
Use doInBackground() just for tasks that :
Take some time
Are not UI related
Then you can implement AsyncTask.onPostExecute() to run code to handle those results on main UI thread from AsyncTask
From JavaDoc for AsyncTask.onPostExecute():
"Runs on the UI thread after doInBackground. ... "
As the others have pointed out, you can use runOnUiThread. But, it seems a little odd that you would want to do that in your doInBackground. If you are wanting to indicate progress to the user you would want to handle that in AsyncTask.onProgressUpdate and call publishProgress in your doInBackground.
You can read more about AsyncTask here: http://developer.android.com/reference/android/os/AsyncTask.html
-Dan
I tried to change the textview more than once in my activity and then again in my AsyncTask. Is this possible it gave me a error on the line where i changed it the second time.
You can change it as often as you want.
But keep in mind that an AsyncTask is a seperate thread. If you want to change UI-components, you have to do this in the UI-thread.
This means: If you want to change a UI-control inside the AsyncTask class, you have to do it either inside onPreExecute(), onProgressUpdate() or onPostExecute(). These run in the UI thread and can manipulate Views and layouts. You can't do it inside doInBackground().
Edit: If you want to know more, read the official documentation:
Processes and Threads
TextView in Android is mutable - it can be written more than once using setText();
Here's the docs.
http://developer.android.com/reference/android/widget/TextView.html#setText(java.lang.CharSequence, android.widget.TextView.BufferType)
A more likely problem is that the variable for the TextView is null in the handler function of the AsyncTask. Check that the textView variable is available to the scope of your asynctask.
Question arising from my first attempt at using an Async object.
I have a main activity in which some TextViews have been created programmatically and added to a LinearLayout. Also a button, when this is clicked, an AsyncTask object is instantiated and results are obtained in the doInBackGround method. How should the result strings be transferred to the TextViews?
a) by calling the SetText methods of these TextViews from the onPostExecute method,
b) using intents and an onActivityResult method in the main activity
c) some other way (a clue would be nice!)
Thanks!
I would go for the AsyncTask option. I'm guessing that as you already have one in place, the obtaining results part that happens when you click the button takes time, so it's good design to have that in the doInBackground method of the AsyncTask.
Then you can call each TextView's setText(...) method in the onPostExecute method in your AsyncTask. Or, it's more suitable, you can update each view as you get the result by using the publishProgress(...) and onProgressUpdate(...) methods (see the AsyncTask documentation) during the background calculations, instead of having to wait until the end.
Just bear in mind that you can only call setText(...) from the onPreExecute, onProgressUpdate and onPostExecute methods, as (at least it seems this way from your explanation) the views have been created on the UI thread, so they can only be modified from that same thread, which those methods run on.
When using an AsyncTask, you can use the doInBackground method for processing, and the onPostExecute to update any UI changes. So, if you need to use an AsyncTask, I'd go for option A.
Make the TextViews private and define them in doInBackground, then you can just call the setText method in onPostExecute or as the last thing in doInBackground, but i would recommend onPostExecute.
I am getting a "CalledFromWrongThreadException" error when I try to update a TextView (via a listener) from an AsyncTask onProgressUpdate.
If I try to update the same TextView from onPostExecute everything works.
I have been testing using code based on
https://github.com/commonsguy/cw-android/tree/master/Service/WeatherAPI
(with a small mod that does an onProgressUpdate in the doInBackgroundMethod, and adds the onProgressUpdate override)
Any suggestion to fixes would be most appreciated.
Are you calling onProgressUpdate() from your code? You shouldn't do it. Use publishProgress() method.
onProgressUpdate doesn't run on UI thread, so you can't access views from this method. If you want to update progress, you should find a way to synchronize your AsyncTask with your activity. A way that I'm using is to create an interface with methods like onBegin, onUpdate and onFinish. You should implement this interface in your main activity class. Then you should have an instance of your activity inside your AsyncTask. In the onProgressUpdate method you just call the onUpdate method in your activity and update the layout. Hope I've explained it clear enough.