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!
Related
Given that posting a task with post() puts the Runnable in a queue, is there any difference between
protected void onCreate(Bundle savedInstanceState) {
Log.d("UI thread", "Do something");
}
and
protected void onCreate(Bundle savedInstanceState) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d("UI thread", "Do something");
}
});
}
?
In both cases, there should only be one thread running and no concurrency happening - right?
Then what's the benefit in creating a handler that attaches to the UI thread and running tasks on it?
The timing is different. In the first snippet the code is executed as part of the onCreate execution so it is guaranteed to finish before onCreate returns, in the second snippet, it is executed some time later (maybe after several other callbacks).
Then what's the benefit in creating a handler that attaches to the UI thread and running tasks on it?
Your example provides only a minimal "use case" which most developers may never experience. In your example, you might want to start a background service but you wanted to ensure that the method that starts the service completes before performing that work, your example would accomplish that. Additionally, you might want to ensure that the service construction is prioritized on the main/UI thread. This approach means you don't have to add a comment like "put this code at the end of this method" or have other "inherent code dependencies" - the call to the handler guarantees post-method/end of method execution. Not really "normal" so...
A more useful example is when you have a background thread that needs to update the UI. It can do the necessary processing in the background, then create a handler that will execute on the UI thread appropriately. This is very common and is implemented in AsyncTask for example (in its getMainHandler() method - https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java#L282)
Also, handlers allow for post-delayed execution of Runnables. A post-delayed execution is often beneficial for situations where immediate screen display is more important than complete screen display. In most cases a developer should "bake-in" a delay and have the screen show a loading spinner or some other UI/UX decoration, but if there isn't a requirement to specify the length of the delay, the example you gave would post the runnable on the main thread looper queue to execute ASAP. That might be exactly what you want to do, or it might be confusing to other developers that might have to maintain your code (for example, the reason you asked this question).
So from what I've read, Android's AsyncTask is a great way to asynchronously load information from the Internet. However, I don't want to block up the UI and prevent the user from interacting with it.
A basic description of my problem.
Currently, I am using websockets in order to send/receive data from a web server. On events like a user entering the room, a song being added or removed from a playlist, a song being upvoted or downvoted, or one song ending and another one beginning, the UI must be updated in order to indicate changes. But ideally, these changes will be occurring very frequently, which means that constantly blocking the UI in order to refresh it would be cumbersome and annoying.
How would I update my UI without interrupting the user in their activities? Would AsyncTask suffice?
The asyncTask does not block the UI. It runs on a separate thread to send / receive the data from the web, and then returns the results. When you receive the results back, you can update the UI as you choose.
Your UI will not be stopped while the asyncTask is performing its background work. You can try it out by by building one in your activity and simply sleeping for some amount of time (let's say five seconds) in the doInBackground method. You will see that your UI is still functional during that five seconds.
Edit: You can do just about anything with the results you get back and it won't interrupt your UI either. If that's not the case, you'll probably want to look at optimizing what you are doing with your in memory objects. Anything not stored in memory should probably be retrieved or written to disk, database, or internet endpoint with an AsyncTask. As the commenter points out above, this is not the only way to use other threads, but it's easy and will probably work if you're making a reasonable web request and expect users to have a decent connection. You will just want to make sure you have timeouts and exceptions covered so that your app doesn't crash if the task takes longer than expected.
public class LoadCommentList extends AsyncTask<Integer, Integer, List<Comment>> {
private String commentSubject;
public LoadCommentList(commentSubject){
this.commentSubject = commentSubject;
}
// Do the long-running work in here
protected List<Comment> doInBackground(Integer... params) {
// the data producer is a class I have to handle web calls
DataProducer dp = DataProducer.getInstance();
// here, the getComments method makes the http call to get comments
List<Comment> comments = dp.getComments(commentSubject);
return comments;
}
// This is called each time you call publishProgress()
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
// This is called when doInBackground() is finished
protected void onPostExecute(List<Comment> comments) {
// calls a method in the activity to update the ui
updateUI(comments);
}
}
There are cleaner examples actually using the Integer... params for example, but this is just something I had handy as an example.
I don't know where you read that but asyn task are worst way to make web service call this days. You should use Retrofit for service call, it is 8 Times faster and handle UI update smoothly.
Read more about this here :-
http://googleweblight.com/?lite_url=http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit&ei=qR4bQU5c&lc=en-IN&s=1&m=260&host=www.google.co.in&ts=1465531978&sig=APY536z0v15lfX3G6KY4nls4wf1kzttJdA
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'm using the bump android sdk. I have a broadcast receiver and i would like to update some elements from my ui depending on different intent filters. for example
else if (action.equals(BumpAPIIntents.NOT_MATCHED)) {
Log.i("Bump Test", "Not matched.");
BumpTest inst = BumpTest.instance();
if(inst != null) {
inst.UpdateMyText("testing");
}
Problem is even though in logcat i can see the log entry the textview update method doesnt seem to be called
Am I doing something wrong?
You aren't allowed to update the UI from other threads (like the one that calls the BroadcastReceiver). You'll have to use a simple AsyncTask class. It was created for the sole purpose of updating the UI after performing actions that will take a long time to complete. It's a good idea to put things like requesting resources from the internet in an AsyncTask because it doesn't block the UI thread from executing. The nice side effect is it calls a function in your main program when it's done, and this call is done on the UI thread.
I want to ensure that I don't slow down my app's startup time and need to start a background task that's unrelated to user input--for instance, filling a cache.
If I start an AsyncTask from my onCreate method, when will the doInBackground method actually begin to execute? (Assume a single core device)
Is it possible that Android could schedule it before onCreate/onResume has completed, or is it smart enough to recognize that the background thread shouldn't run until the UI thread is completely finished?
If you look at AsyncTask source code you will see that it is just using ThreadPoolExecutor or serial executor for running tasks. Default internal behavior depends on Android version (from AsyncTask docs):
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
But anyway doInBackground execution is not connected with Activity lifecycle so AsyncTask may be executed at almost any time. This depends only on how many tasks you have already started, on default Executor which is used by AsyncTask and on thread scheduler.
I usually use AsyncTasks in onCreate() like this:
private MySuperSpecialTask mySuperSpecialTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(...);
// [...]
mySuperSpecialTask = new MySuperSpecialTask();
mySuperSpecialTask.execute();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mySuperSpecialTask != null) {
mySuperSpecialTask.cancel(true);
}
}
This makes sure that everything is initialized before the task gets started.
actually strictly speaking there is no execution order of your UI code and starting the asynctask I found out. Normally one does not experience this, however, if your UI thread takes longer for some reason, eg waiting for external input etc, the asynctask might have gotten started BEFORE UI code has finished.
Writing UI code is just a request to the Android system and this waits in the execution loop. So if asynctask starts before that because there are enough ressources (or as mentioned UI thread is delayed for whatever reason) there is no execution order guarantee.
One easy way to enforce this is - in case you don't mind and you can be sure that it is suffiencient - delay the starting of the asynctask with ScheduledExecutorService or a "cleaner" way would be to implement some kind of gate keeper that waits for a flag to be set to true and then start the asynctask. Or you may even have a while-loop at the beginning of your asynctask that waits for the flag to be set to true, like in many communication situations with external devices.
The flag would be set to true AFTER you can be (normally) sure that your UI has finished.