How to keep UI thread waiting until i get data from AsyncTask.
i trying to load some information and image from server and display it into textview and imageview respectively. But UI thread access the field before background thread complete its task. So null value is retrieved and application get crashed.
You can update the UI in onPostExecute of AsyncTask after doing your background tasks.
For the crash, by accessing the field on UI thread => You need to shift this code also to the onPostExecute method.
So the required data will be available, the field will have a value.
So the crash issue can be resolved.
If you are building an application that basically scrapes the html source and then you manipulate this "string", what you can do is
private class Scrapper extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
//Get the source here
}
Then in the onCreate Method
Scrapper scrapper = new Scrapper();
String URLSource = scrapper.execute("url here").get();
//Additional code to manipulate the string
However it is generally not recommended to do it this way, since apparently it will put the entire UI Thread on hold and there will be a long delay if the source is large.
Related
I also faced with the NetworkOnMainThreadException in my application but I don't see how to resolve it.
I have a class with a getter method. Like:
public ArrayList<News> get(int i){
// get the list of news from a HTML on the net. The news are split up into web pages on the site
// and i is the page number
return NewsParser(i);
}
Since Android throws the exception I come up with an idea of a downloader class which downloads the HTML content in a separate thread
pubic ArrayList<News> get(int i){
Downloader dl = new Downloader(i);
String HTMLcontent = dl.getContent(); <-- AsyncTask starts in getContent()
return NewsParser(HTMLcontent); <-- What happens here in the main thread???
}
Any ideas/best practices for this problem?
Just looking at your code and your question, it seems like you don't have a very solid understanding of how AsyncTask (or threads in general) works.
I would recommend reading this article.
Basically, your AsyncTask should query the web URL and download the data. Once the data is complete, your AsyncTask should send the HTMLContent to a handler object. The handler will be running on your main thread, so you can display the information to the user at that point.
You shouldn't be calling
dl.getContent();
to retrieve the content. AsyncTask runs on a separate thread, so you can't just call methods like this from your main thread. You need to create the Downloader object (like you did) and then call
dl.execute();
to start the AsyncTask.
run the get method inside a thread,
new Thread(new Runnable() {
#Override
public void run() {
// call get method here
}
}).start();
Since Honeycomb (Android 3.0) you can't use Networking Operations in the MainThread to avoid freezes on the Phone. This is important in order to make your app responsive.
More info:
NetworkOnMainThreadException
Responsiveness
I am using this following code for getting all songs stored in the sdcard.
https://stackoverflow.com/a/12227047/2714061
Well why does this code take so long to return this list of songs.
I have included this code in a function which is called from the oncreate method in my player's playlist.
This is what happens.
1: When the application runs is executed for the first time on my android ph, the playlist has nothing to show, and hence is seen empty.
2: Well after for instance-> 30sec when I again call for the playlist it returns instantly all the songs.
Hence, giving the feel as though this thing takes time to execute?
Why does this happen?
How about using an asynchronous task, reading a file or downloading something, takes time that requires the user to wait, you must think of using an Asynchronous task for this purpose,
1: From the developer reference we have :
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers. http://developer.android.com/reference/android/os/AsyncTask.html
An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
2: So you may include an Async task class as:
class DoBackgroundTask extends AsyncTask<URL, Void, ArrayList> {
/*
URL is the file directory or URL to be fetched, remember we can pass an array of URLs,
Void is simple void for the progress parameter, you may change it to Integer or Double if you also want to do something on progress,
Arraylist is the type of object returned by doInBackground() method.
*/
#Override
protected ArrayList doInBackground(URL... url) {
//Do your background work here
//i.e. fetch your file list here
return fileList; // return your fileList as an ArrayList
}
protected void onPostExecute(ArrayList result) {
//Do updates on GUI here
//i.e. fetch your file list from result and show on GUI
}
#Override
protected void onProgressUpdate(Integer... values) {
// Do something on progress update
}
}
//Meanwhile, you may show a progressbar while the files load, or are fetched.
This AsyncTask can be called from you onCreate method by calling its execute method and passing the arguments to it:
new DoBackgroundTask().execute(URL);
3: And at last, there is also a very nice tutorial about AsyncTasks here, http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
I have an AsyncTask which which takes an ArrayList of music files to play. In the doInBackground method, I loop through the ArrayList and play the songs one-by-one. I'd like to put a status message on a TextView of the UI or something to indicate which song is playing, but getting the error Only the original thread that created a view hierarchy can touch its views. If I only update the UI widgets from onPreExecute() and onPostExecute() the list has already been played. Is there a way to use onProgressUpdate or other AsyncTask method to do this?
This is certainly possible. Here's a basic example if you had Strings you wanted to display for song name, album name, and artist name (I haven't fully implemented the AsyncTask, just the parts relevant to onProgressUpdate):
private class myAsyncTask extends AsyncTask<Void, String, Void>
{
protected Void doInBackground(Void... voids)
{
//Get some list of songs, named songs
for(Song song in songs)//This is the loop where you're playing your songs
{
publishProgress(song.name, song.album, song.artist);
//Play the song and wait for it to finish
}
return null;
}
protected void onProgressUpdate(String... songData)
{
//Assuming three text views exist to display your data
nameTextView.setText(songData[0]);
albumTextView.setText(songData[1]);
artistTextView.setText(songData[2]);
}
}
The important things to note are the the second class in the angle brackets is the type of parameters for onProgressUpdate, and that publishProgress gets called in doInBackground to trigger onProgressUpdate. Most examples that you'll find for onProgressUpdate involve increasing the fill on a ProgressBar, but the method runs on the UI thread and can interact with any Views that can be accessed by your AsyncTask. If you're still having some trouble, post your current AsyncTask so that it'll be easier to help integrate this example class into what you already have. Here are the docs for AsyncTask for more information.Hope this helps!
You should be able to use onProgressUpdate() to perform the update from the UI thread. Or, you could do it like this (which is typical when not using AsyncTask).
Post an event on the UI thread that updates your UI like this:
view.post( new Runnable() {
#Override
public void run() {
// Update your UI
}
});
It will be running on the UI thread so it can access and update the view.
Yes there is.
When you decalre your AsyncTask, you decalre the types that go into each part of the task:
public class MyTask extends AsyncTask<URL,Integer,Long> {
.
.
.
}
The types in order, for this example:
URL gets passed to doInBackground via execute
Integer gets to onProgressUpdate (via publishProgress)
Long gets to onPostExecute, also the return value of doInBackground
In your doInBackground(), you can call publishProgress(), which will in turn call onProgessUpdate() on the main thread (assuming you created your AsyncTask on the main thread).
There is a complete example in the reference docs under Usage (link).
I don't understand what I am supposed to put in here and where these arguments end up? What exactly should I put, and where exactly will it go? Do I need to include all 3 or can I include 1,2,20?
Google's Android Documentation Says that :
An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
AsyncTask's generic types :
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
Result, the type of the result of the background computation.
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
You Can further refer : http://developer.android.com/reference/android/os/AsyncTask.html
Or You Can clear whats the role of AsyncTask by refering Sankar-Ganesh's Blog
Well The structure of a typical AsyncTask class goes like :
private class MyTask extends AsyncTask<X, Y, Z>
protected void onPreExecute(){
}
This method is executed before starting the new Thread. There is no input/output values, so just initialize variables or whatever you think you need to do.
protected Z doInBackground(X...x){
}
The most important method in the AsyncTask class. You have to place here all the stuff you want to do in the background, in a different thread from the main one. Here we have as an input value an array of objects from the type “X” (Do you see in the header? We have “...extends AsyncTask” These are the TYPES of the input parameters) and returns an object from the type “Z”.
protected void onProgressUpdate(Y y){
}
This method is called using the method publishProgress(y) and it is usually used when you want to show any progress or information in the main screen, like a progress bar showing the progress of the operation you are doing in the background.
protected void onPostExecute(Z z){
}
This method is called after the operation in the background is done. As an input parameter you will receive the output parameter of the doInBackground method.
What about the X, Y and Z types?
As you can deduce from the above structure:
X – The type of the input variables value you want to set to the background process. This can be an array of objects.
Y – The type of the objects you are going to enter in the onProgressUpdate method.
Z – The type of the result from the operations you have done in the background process.
How do we call this task from an outside class? Just with the following two lines:
MyTask myTask = new MyTask();
myTask.execute(x);
Where x is the input parameter of the type X.
Once we have our task running, we can find out its status from “outside”. Using the “getStatus()” method.
myTask.getStatus();
and we can receive the following status:
RUNNING - Indicates that the task is running.
PENDING - Indicates that the task has not been executed yet.
FINISHED - Indicates that onPostExecute(Z) has finished.
Hints about using AsyncTask
Do not call the methods onPreExecute, doInBackground and onPostExecute manually. This is automatically done by the system.
You cannot call an AsyncTask inside another AsyncTask or Thread. The call of the method execute must be done in the UI Thread.
The method onPostExecute is executed in the UI Thread (here you can call another AsyncTask!).
The input parameters of the task can be an Object array, this way you can put whatever objects and types you want.
I'm too late to the party but thought this might help someone.
Keep it simple!
An AsyncTask is background task which runs in the background thread. It takes an Input, performs Progress and gives Output.
ie AsyncTask<Input,Progress,Output>.
In my opinion the main source of confusion comes when we try to memorize the parameters in the AsyncTask.
The key is Don't memorize.
If you can visualize what your task really needs to do then writing the AsyncTask with the correct signature would be a piece of cake.
Just figure out what your Input, Progress and Output are and you will be good to go.
For example:
Heart of the AsyncTask!
doInBackgound() method is the most important method in an AsyncTask because
Only this method runs in the background thread and publish data to UI thread.
Its signature changes with the AsyncTask parameters.
So lets see the relationship
doInBackground() and onPostExecute(),onProgressUpdate() are also related
Show me the code
So how will I write the code for DownloadTask?
DownloadTask extends AsyncTask<String,Integer,String>{
#Override
public void onPreExecute()
{}
#Override
public String doInbackGround(String... params)
{
// Download code
int downloadPerc = // calculate that
publish(downloadPerc);
return "Download Success";
}
#Override
public void onPostExecute(String result)
{
super.onPostExecute(result);
}
#Override
public void onProgressUpdate(Integer... params)
{
// show in spinner, access UI elements
}
}
How will you run this Task
new DownLoadTask().execute("Paradise.mp3");
Refer to following links:
http://developer.android.com/reference/android/os/AsyncTask.html
http://labs.makemachine.net/2010/05/android-asynctask-example/
You cannot pass more than three arguments, if you want to pass only 1 argument then use void for the other two arguments.
1. private class DownloadFilesTask extends AsyncTask<URL, Integer, Long>
2. protected class InitTask extends AsyncTask<Context, Integer, Integer>
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
in Short, There are 3 parameters in AsyncTask
parameters for Input use in DoInBackground(String... params)
parameters for show status of progress use in OnProgressUpdate(String... status)
parameters for result use in OnPostExcute(String... result)
Note : - [Type of parameters can vary depending on your requirement]
Hey, I have an application which logs onto a few sites using defaulthttpclient and I've found I'm going to need to use the AsyncTask as the requests hold up the UI thread. In my code, I create an instance of a state class i.e. State state = new O2State(); with different states for different sites.
I then call state.logon(String username, String password); which returns a string containing details of the result so:
String result = state.logon(username, password);
I've been trying to implement asynctasks to run this code in another thread and return the string back to the UI thread on completion. The idea is I will display a progress dialog, run the thread, and on complete, will display a dialog with the result.
I've been looking at this example:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Where I'm stuck is:
I don't think I'll need any arguments, but doinbackground seems to require a list of parameters. I'm also unfamiliar with this time of method argument declaration.
Secondly:
I'm not sure how to return the resulting string when the thread is finished executing. Should I just create a "DoThisWhenTheThreadIsFinished(String result)" and call this from onPostExecute?
Anyway, I hope this isn't too confusing to read and I'd really appreciate any help you can offer.
Thanks
Where you don't need parameters just specify the type (e.g. String) and ignore it, or you could use the Void class (note the capital V).
What you suggest for how to return control back to the UI thread to reflect the update is a good approach. i.e. in onPostExecute() call a method on the activity to update the UI.
As a general rule if any operations will take more than a couple of hundred milliseconds, use a separate thread. You may also want to use a rotating progress indicator to show the app is doing something.
(when people answer your questions, always rate the ones you like, and pick one as the "best" answer. you get points doing this, and it helps others later).