I have an activity which gets called every time a Call is ended. This activity has below AsyncTask.
UploadRecordings uploadRecordings = new UploadRecordings();
uploadRecordings.execute(context);
Now when I get many Calls one after another, everytime new AysncTask is created. But Android limits the number of AsyncTask to 5. So problem is I want to check if a AsyncTask is already running, and if found running, don't create a new AsyncTask. I want to create a new AsyncTask if there is no AsyncTask running.
Any Help be Appreciated.
Use getStatus() to get the status of your AsyncTask. If status is AsyncTask.Status.RUNNING then your task is running.
check this way
if(uploadRecordings.getStatus() == AsyncTask.Status.RUNNING){
// My AsyncTask is currently doing work in doInBackground()
}
For More Detail Read : Android, AsyncTask, check status?
You can use getStatus ()
Returns the current status of this task.
if(YourAsyncTaskOBJ.getStatus() == AsyncTask.Status.RUNNING)
{
// AsyncTask Running
}
Read How to check if Async Task is already running
Override onPostExecute() method of AsyncTask, which is executed whenever a call is completed. Set some flags in onPostExecute() and proceed accordingly.
Dealing with AsyncTask
Put the AsyncTask in a Fragment.
Using fragments probably is the cleanest way to handle configuration changes. By default, Android destroys and recreates the fragments just like activities, however, fragments have the ability to retain their instances, simply by calling: setRetainInstance(true), in one of its callback methods, for example in the onCreate().
please find full implementation and description to deal with AsyncTask.
Handle Android AsyncTask
If you want to create a single AsyncTask when nothing is already running, you can do something like:
if(uploadRecordings == null || uploadRecordings.getStatus() != AsyncTask.Status.RUNNING){
uploadRecordings = new UploadRecordings();
uploadRecordings.execute(context);
}
This assumes that your uploadRecordings is a member variable. e.g.
private UploadRecordings uploadRecordings = null;
Related
OK so I have an Android app which has a listview on a fragment being loaded on the mainactivity. The list view contains an imageview which is loaded with an image from the devices external storage via an adapter which in turn calls an AsyncTask object called BackgroundImageLoader.
At this point if I run my app everything work great and the images show nearly instantaneously.
To give more detail about that process....
On the listview's adapter's bindView method I call a method which invokes the following:
BackgroundImageLoader loader = new BackgroundImageLoader(photoID, imageView);
loader.execute();
Now after I got the above code working perfectly I wrote some logic to "purge old photos". This logic was put in an AsyncTask object named AutoPurgePhotos_Task. Basically I want to run the task once on startup of the app but I just want it to run in the background so as not to interfere with the UI. I have tried launching it from the tail-end of the Applications onCreate() method and I have tried launching it from the MainActivity's onCreate() method. The results are such that the purging logic runs and works perfectly. And while it is running in the background my UI seems to be working as well with EVERYTHING EXCEPT the BackgroundImageLoader AsyncTask. None of the photos will begin to show until the AutoPurge task completes. Even to prove it has nothing to do with what I am doing in the task, I commented out all of my business logic and just have the task sleeping.
public class AutoPurgePhotos_Task extends AsyncTask<Void, Void, Void> {
public AutoPurgePhotos_Task() {
super();
}
#Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
return null ;
}
}
As a side note I have other asynctask in my app that will not run either until this initial asynctask finishes. Its as if only one asynctask will run at a time. Again all other code that is in my UI thread appears to be running and working just fine while the asynctask is running. It just seems that only one asynctask will run at a time.
Here is how I launch the autopurge task...
AutoPurgePhotos_Task task = new AutoPurgePhotos_Task();
task.execute();
again I have tried launching it from several different areas and no matter where/how I launch it the other asynctask will wait till that one is done before they will run.
Thanks for any help you can give me.
Use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of execute(). Quoting the AsyncTask documentation:
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
So I have a problem and I am wondering how to solve it if it can be solved at all.
I have an external library class called Messenger that defines the method sendMessage(String msg). I also have the following MessengerManager class
public class MessengerManager{
private Messenger messenger;
public MessengerManager(Context context){
messenger = new Messenger(context);
}
public void message(){
String msg = "12435";
messenger.sendMessage(msg);
// Do more stuff
.....
.....
.....
}
}
So the issue is that sendMessage runs asynchronously and starts a new activity. Probably using startActivity() (lets call this Activity A). Hence, the code after sendMessage ("Do more stuff") gets run immediately. However, I need to wait for the newly created activity (Activity A) to return to carry on with the "Do more stuff".
As sendMessage is a method defined in an external library, I cannot change it in any way nor do I have access to its source code.
So, in short, my problem is that sendMessage creates a new thread (using startActivity() probably) and I need to know when this newly created activity ends. However, I have no way of monitoring it since it is defined in an external library. Anyone know how to solve this?
AsyncTask should be what you are looking for.
Let your message() starts an AsyncTask that calls messenger.sendMessage(msg) in doInBackground(). If you care about the result of the AsyncTask, get it in onPostExecute().
http://developer.android.com/reference/android/os/AsyncTask.html
One admittedly ugly way to get around this is to call
Thread.sleep(int milliseconds)
after sendMessage(), and before you continue with the rest of your code. Of course, this will only be helpful if you can fairly accurately estimate how long it will take to get the callback.
The better alternative is as Kaifei is saying. But you won't want the "do more stuff" where it is now. Instead, put it in a new method, and call that method in onPostExecute(). That way, the code will not continue until the AsyncTask has returned.
Edit: Saw your addition about needing the created activity to finish. If that's the case, you're going to somehow need to communicate with that activity (which I can't speak to without seeing all the code). But if you have that, then before "do more stuff", insert
while(!activity.isFinished()) {}
and in that activity, have it set a finished variable to true when it is done (however you define done). So the main thread will run this loop until the activity on the second thread is done, and then the first thread will continue.
Double Edit: Another idea. Let's say that the other activity the user has to complete is some form. In your main activity, after you call sendMessage(), have some popup where the user selects "finished" when they have completed the new activity. Have the program only continue when "finished" has been selected. A bit annoying for the user, but if it's only a single additional tap, that should work.
As you mentioned, sendMessage() runs asynchronously. If it's written properly, it must also have provided a callback interface, whose method will be called when messaging is finished. Move the code in that callback method.
I am new to threading . I have searched many questions related to my problem but I am not able to find the right solution for me. What I am doing is I am using four async tasks to fetch data from four different social media using the THREAD_POOL_EXECUTOR.
code is as follows.
new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
...
mAdapter = new MyAdapter(getActivity(),
(ArrayList<Model>) showList);
mListView.setAdapter(mAdapter);
I want the calls to be in parallel to save the time of fetching data. Now the idea is that i want all the four threads to complete the work and after that I want to display the sorted data as per timestamp. Right now the problem is that my setAdapter get called before the four threads complete fetching data as adapter is set on the UI thread. I want a mechanism to block the UI thread until all four threads complete fetching the data.
I have found that maybe I can use the shutDown() and awaitTermination() methods of ExecutorService . It would be great if anyone can help me in anyway. Thanks a lot
What I would do is:
Create an empty ArrayList in your activity
Pass this arrayList to your adapter and set the adapter on your ListView. setAdapter method will not affect the listView - it will still be empty becase the list is empty.
Start 4 AsyncTasks and fetch data. In onPostExecute() add this data to the ArrayList and invoke notifyDatasetChanged() on the adapter.
You should never block an UI thread because it is just wrong. When you want all data to be shown at once you can make a simple counter, make counter++ in every onPostExecute and invoke notifyDatasetChange() only when counter is 4.
Invoke method shutdown() from ExecutorService.
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html
If you're really okay with blocking the UI thread, try this:
new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
...
AsyncTask.THREAD_POOL_EXECUTOR.shutdown();
while (!AsyncTask.THREAD_POOL_EXECUTOR.isTerminated()) {}
mAdapter = new MyAdapter(getActivity(),
(ArrayList<Model>) showList);
mListView.setAdapter(mAdapter);
In most cases though, blocking the UI thread isn't a good idea.
I could successfully handle the problem without going deeo into threading. I used the simple concept of making booleans true after execution of each thread. And in the UI thread I checked for infinte time i.e
while(true)
{
if(flag1 && flag2 && flag3 && flag4)
{
//set the adapter and make the flags false
break;
}
}
Dont forget to make the falgs false otherwise execution will go on for indefinite time.
I download a RSS Feed and then parse it in a class, the rssfeed is saved as a custom object; however the code blocks as the feed is relatively big and the Android typically works only on EDGE.
I want to put the downloading of the file into an AsyncTask with an indefinite progress dialog.
I also want to be able to access the rssfeed object after its downloaded in the ASynctask from within the Main Thread. How do I reference it?
When you build an AsyncTask, the third generic argument is the Result, and when you execute the asyn task, you can call get to retrieve the Result object. Depending on what you need to do with the object on the main thread, you can also override the AsyncTask's onPostExecute method which will be run on the main thread after doInBackground completes. This is probably the best bet, to override onPostExecute on the AsyncTask.
I'm using an AsyncTask class to add, remove and clear items from my ArrayAdapter. Unfortunately, when any of those tasks are run, the ArrayAdapter wants to notifyDataSetChanged(), which requires that the thread be run on the uiThread.
If I use runOnUiThread(new Runnable(){...}); in order to update an ArrayAdapter Asynchronously, doesn't that defeat the purpose of trying to update it in a new Thread to begin with?
What is the best approach here?
Do .notifyDataSetChanged() insde onPostExecute() method. onPostExecute() method runs on Ui-Thread. If your app requires to periodically update during execution of doInBackground() method then use publishProgress() (which will envoke onProgressUpdate() method) and call notifyDataSetChanged() inside onProgressUpdate() method, which also runs on Ui-thread.
Just to add something to what everyone else already said, after your task is done running, you might want to set the adapter (or a new one) again for the view you are working with.
AFAIK depending on your code, after notifyDataSetChanged or after refreshing the cursor, the view might not update right away if you are not working with a reference.
If you leave your activity and when you come back, the view is updated, you probably need to set the adapter again.
To answer your first question, calling runOnUiThread doesn't defeat the purpose as long as the only thing you call on the UI thread is notifyDataSetChanged(). Do all your actual, potential long running, tasks in the AsycnAdpater and then when you're ready to tell the activity things have changed, call runOnUiThread(). It will only run the commands you specify in the Runnable you pass to it.
That said, why not instead of using an AsyncTask, try using an AsyncTaskLoader. AsycnTaskLoaders were designed almost specifically for populating lists asynchronously. They weren't introduced until API level 10, but you can still access them from older API levels by using the android Support Package.