I have a very sporadic failure in my app I'm trying to resolve. On entry to the app, at one point the main UI thread processing ends and passes control to a background thread to retrieve some data. When the data is retrieved, control passes back to the main UI thread to process it for display. However, on some rare occassions (it works 99% of the time), the AsyncTask seems to be failing to be called leaving the app in a poor static state forever waiting for the AsyncTask to complete.
Here's a snapshot of the code in the Activity:
//method call from main UI thread
private void fetchSomeData() {
Log.d("myTag", "In fecthSomeData()");
new ReadFileAsyncTask<DataModel>().execute(this);
}
Here's the ReadFileAsyncTask implementation:
public class ReadFileAsyncTask<A> extends AsyncTask<I_ReadFileListener<A>, Void, A>
{
I_ReadFileListener<A> listener;
#Override
#SuppressWarnings("unchecked")
protected A doInBackground(I_ReadFileListener<A>... params)
{
listener = params[0];
Log.d("mytag", "BACKGROUND: Loading " + listener.getFilename() + " from disk");
A fileContents = (A) FileUtils.readDataFromInternalStorage(listener.getContext(), listener.getFilename());
return fileContents;
}
#Override
protected void onPostExecute(A result)
{
Log.d("myTag", "FOREGROUND: Executing onFileRetrieved listener");
listener.onFileRetrieved(result);
}
}
Capturing the logs on this rare failure yeilds:
In fetchSomeData()
...
(Other log messages from other interactions with the activity such as menu creation and navigation initialization)
but, crucially, not the log statement from the second line of code in the doInBackground method. One thought I had was that this log statement was failing, but I'm not seeing any force stop messages, error in my logs or ACRA crash reports. The application is still active (I can navigate to other activities and back) so I'm at a loss as to what might stop this background thread from running properly. Any ideas?
Sadly AsyncTask is not suitable for critical code execution since, depending on the ThreadPool base and max size, your AsyncTask may never execute.
Moreover, the onPostExecute method could be called when the Activity it is referring (i.e. its creating context) has already been destroyed. You have no way to synchronize with it rather then maybe using join() on the AsyncThread from the UI Thread.
Even though I've seen doing this also in the Android Camera App it isn't a good idea to block the UI Thread waiting for an event since you coulg get an ANR (Application Not Running) notification.
Take a look at this: Is AsyncTask really conceptually flawed or am I just missing something?
Consider using IntentServices, HandlerThread or ThreadPoolExecutors if you need a possibly better way to synchronize your worker thread with your your UIThread.
From http://developer.android.com/training/run-background-service/create-service.html:
Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask
Related
I'm currently using Firebase JobDispatcher to run a periodic check in the background using the service intent (registered on boot, install & update). This is working correctly, and it spawns it's own thread separate from the main thread, so I don't lock the UI, and it kills the thread properly so garbage collection doesn't become a problem.
I would also like to trigger this same exact work from the main thread in-app. The problem is that running a jobdispatcher onCreate triggers the job to run in the main UI thread, and not in a background thread. One of my functions can generate A LOT of objects, so even though it properly runs, it kills usability in the app because the GC never can get rid of all the junk.
How can I run an existing JobDispatcher job on demand from the main thread, but still in a separate thread?
Thanks so much for your help.
Edits for clarification of this specific usage
My particular case involves a first run, where UpdateNetworkerJob.class can take several minutes to run. The phoneHistoryCheck.GetLastCallChecked() function has a loop which makes several calls to Firebase, both retrieving and putting information.
9/12 Update
Subsequent runs are very quick, and AsyncTask can work. However I am finding I need a more robust solution and am currently looking at ThreadPoolExecutor. It's possible that the GetLastCallChecked() function is throwing too much at the Firebase Engine and it causing the main thread's calls to Firebase to be way down in the noise as it catches up. I'm working on sorting this part out.
Code in main thread to start the work:
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(trackedContactListActivity.this));
Job myJob = dispatcher.newJobBuilder()
.setService(UpdateNetworkerJob.class)
.setTag("UpdateNetworkerService")
.setTrigger(Trigger.NOW)
.setConstraints(
Constraint.ON_ANY_NETWORK
)
.build();
dispatcher.mustSchedule(myJob);
UpdateNetworkerJob.class
public class UpdateNetworkerJob extends JobService {
private static final String TAG = "UpdateNetworkerJob";
#Override
public boolean onStartJob(final JobParameters params) {
Log.d(TAG, "UpdateNetworkerJob is running with params: " + params);
PhoneHistoryCheck phoneHistoryCheck = new PhoneHistoryCheck();
phoneHistoryCheck.GetLastCallChecked(UpdateNetworkerJob.this);
return false;
}
#Override
public boolean onStopJob(JobParameters params) {
// Stop tracking these job parameters, as we've 'finished' executing.
//sendMessage(MSG_COLOR_STOP, params.getJobId());
Log.d(TAG, "on stop job: " + params);
// Return false to drop the job.
return false;
}
}
Doesn't AsyncTask have limitations on how long things inside it can run? The first time these run in my application they can run for several minutes.
You can find answers to your queries in Threading performance article.
When using AsyncTask, there are a few important performance aspects to keep in mind.
First, by default, an app pushes all of the AsyncTask objects it creates into a single thread. Therefore, they execute in serial fashion, and—as with the main thread—an especially long work packet can block the queue. For this reason, we suggest that you only use AsyncTask to handle work items shorter than 5ms in duration
HandlerThread and ThreadPoolExecutor provides other alternatives.
You can find example code of HandlerThread in this post:
Call Main thread from secondary thread in Android
Please call your service intent from the doinBackground function of an Asynctask. Example is here : Asynctask documentation
you can control the Asynctask from your UI without holding the UI for results.
I have some fragments loaded in a ViewPager, where each "page" is loaded from a row in a cursor. Each fragment shows an image (JPEG) on the device. When the user dismisses the fragment (i.e swipe/page change, hits back/up, or just closes the app entirely) I want to invoke a method which opens the JPEG file for writing and does an update of its metadata. The actual work is eventually handled by the Apache Commons Imaging library.
I've implemented this by invoking my saveToFile() method from each fragment's life cycle onStop() handler. Does this mean the entire file operation ends up running on the UI thread? Should I definitely set up an AsyncTask for this?
Say the file write for some reason suddenly (for some jpeg) should take a long time, eg 2 minutes. What would then happen? Would the UI just wait (freeze) at this page/fragment before resuming? Or would the process (write to file) carry on "in the background" somehow? Or would the process just be killed, stopped short mid-process?
The way I have this wired up currently (onStop invoking saveToFile(), which calls up the imaging library and then updates the file) seems to work as it should. Even if I end the app, I still see my Toast text popping up, saying "Writing to file..." Seemingly, the process is never disturbed, and I can't say I'm experiencing any UI lag.
onStop() handler. Does this mean the entire file operation ends up
running on the UI thread? Should I definitely set up an AsyncTask for
this?
YES
An AsyncTask has several parts: a doInBackground method that does, in fact, run on a separate thread and the onPostExecute method that runs on the UI thread.
You can also use some sort of observer pattern such as EventBus to run async and post results to the UI.
Say the file write for some reason suddenly (for some jpeg) should
take a long time, eg 2 minutes. What would then happen? Would the UI
just wait (freeze)
The application will crash because Android will forcefully close it due to ANR (Application Not Responding).
Refer to the official documentation for details on this: https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by
default the "UI thread" or "main thread"). This means anything your
application is doing in the UI thread that takes a long time to
complete can trigger the ANR dialog because your application is not
giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little
work as possible on that thread. In particular, activities should do
as little as possible to set up in key life-cycle methods such as
onCreate() and onResume(). Potentially long running operations such as
network or database operations, or computationally expensive
calculations such as resizing bitmaps should be done in a worker
thread (or in the case of databases operations, via an asynchronous
request).
The most effective way to create a worker thread for longer operations
is with the AsyncTask class.
Here is what I recommend though. Use the above mentioned, EventBus and create a BaseActivity which will automatically save the data for you onClose() by firing an event that runs Async. You then extend that base activity in all the places where you need autosave capabilities.
Here's what I mean with an example that uses EventBus.
public abstract class BaseActivity extends Activity{
#Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
#Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
#Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}
I am running into a strange problem...
My application is meant to do some webservice calls on a separate thread. Once the webservice call is finished, it would navigate user to a different activity.
In the case when user press the home button or exit current activity it should terminate the webservice if the webservice call thread is still running. Hence I put a thread termination method in the OnPause state.
Here is the method block that is running inside the thread:
private Thread _webserviceThread;
void WebserviceCallThread(){
WebRestult result= WebserviceCall();
if(!result.containsError()){
RunOnUIThread(delegate{
transitionToActivityXYZ();
});
}
}
void RunThreadAction(){
_webserviceThread = new Thread(new ThreadStart(WebserviceCallThread));
_webserviceThread.Start();
}
protected override void OnPause(){
if(_webserviceThread != null && _webserviceThread.IsAlive){
_webserviceThread.Abort();
}
}
After the webservice call is done and begin the transition to another page, It gets to the OnPause state. However, in some strange cases, it would think that the thread is not finished in the OnPause state, even though the activity transition is the last line of the method.
Has anyone ran into this problem before? If so, how did you solve this problem?
Thanks!
I always use AsyncTask for this kind of thing. Not only does it abstract away the explicit thread handling and provide hooks to do everything you want here; it's also a nice way to represent a unit of work that can be used from other activities.
There's a simple example in this post part way down, but it doesn't use the generic parameters which are quite handy.
Why not use Task Parallel Library,
It is standard .NET, and with AsyncTask, it is only recommended for tasks that take less than few seconds. see the Documentation
AsyncTasks should ideally be used for short operations (a few seconds
at the most.) If you need to keep threads running for long periods of
time, it is highly recommended you use the various APIs provided by
the java.util.concurrent
Below is an example for how to use Task Parallel Library, taken from here
private void loginWithTaskLibrary()
{
_progressDialog.Show();
Task.Factory
.StartNew(() =>
_loginService.Login("greg")
)
.ContinueWith(task =>
RunOnUiThread(() =>
onSuccessfulLogin()
)
);
}
I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running
You have already some answers to your question, but I think it worths a summary ...
What you need
When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.
You can achieve that in 2 ways:
Using Thread:
This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.
Using AsyncTask:
Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.
What you don't need
Service
This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.
IntentService
This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.
Regards.
an Android Service is not in a background thread.
Therefore you should have a Service running that will start an ASyncTask each time you want to poll.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.
Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.
As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.
Here you got with AsyncTask fundamentals and some tutorials
And here you got with IntentService fundamentals and tutorials
Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.
EDIT
There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed
If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.
Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.
The thread will run only when the app is running
Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.
Example:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
#Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}
I am writing an android app and I need to be able to do certain things periodically/continuously. I am coming from a C/C++ embedded firmware background and this new-fangled way of doing things is going to take some getting used to. It seems that there is no such thing as a "main loop" in Android, that everything is event-driven... I also understand that by default all code you write operates on the GUI thread, and I should probably make a new thread to execute the equivalent of a "main loop"...
So far what I have is an implementation of the AsyncTask class who's "doInBackground" method contains an infinite loop (my main loop), I create an instance of this class and run it immediately when my app starts. The problem I am having is in the interaction between this thread and the user interface... when something occurs in my main loop thread and I want to update the GUI understand that I must call "publishProgress", which is executed on the GUI thread. There are a few problems with this, primarily that many things I have tried to do in this "onProgressUpdate" method do not work, or do not occur in a predictable amount of time.
My question, is there a better way to accomplish what I am trying to do? In general, what do most people do when they have code that they want to run periodically and/or continuously while their application is running, code that must interact with the user interface in a timely manner (by timely I mean with zero delay).
Thank you.
public class MainLoopThread extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
while(true)
{
//Do stuff
//Update GUI
publishProgress();
}
}
protected void onProgressUpdate(Void...voids)
{
//Update GUI
}
}
It is unclear what you are trying to do, however just let me say using AsyncTask in this way may have negative consequences.
AsyncTask internally uses a thread pool pattern for running the stuff from doInBackground(). On Android OS before 1.6 and starting from 3.0 the pool size is just 1, meaning no parallel computations for a bunch of AsyncTasks. More details on this here.
So, this may result that only this current AsyncTask is running, while others even if started will have to wait untill the current one is done.
Depending on your needs for things to be done periodically Android exposes:
AlarmManager
Handler - it allows to post a runnable on UI thread with a delay or periodically
Timer + Activity.runOnUiThread(Runnable action) inside of TimerTask
UPDATE: basing on your comments it looks like you need a Service, that starts a thread that periodically sends broadcasts with the data for UI. Then your UI (Activity) registers broadcast receivers to catch those broadcasts, extract the data and use for UI updates.
So your saying that onProgessUpdate() isn't working? That seems weird because it should.
Another option that you have is just to make a Thread that loops.
The trick is that if you want to update the UI thread you will have to make a call to view.post() and give it a runnable that will actually perform the update. The idea here is that you must schedule an update on the UI thread, you can't just take it and say NOW!