I have a Handler on the UI thread (created using new Handler(Looper.getMainLooper())) which has a sequence of messages sent to it as soon as the application starts (specifically, after the Application class' onCreate). What I have noticed is that this Handler doesn't seem to receive messages until around the time of the onCreate of the very first Activity. Prior to that point, messages sent to it appear to be lost.
Is this because the UI thread's Looper is not yet ready to execute messages until the first Activity is visible?
Supplementary information
I'm just adding this information in relation to comments below -- it's not part of the specific question.
This Handler is used as part of a mechanism that allows various long-running tasks to cause progress information to appear over the current Activity, using my own version of Eclipse's IProgressMonitor.
When the application starts, a piece of initialisation work is done. This work is a long-running task which involves building data structures based on contents of a file. This piece of initialisation work might have to be repeated later on during use of the application, depending on user operations.
In this application I have my own implementation of IProgressMonitor, an idea based on the class from the Eclipse Platform API. With this, various long-running tasks in the application, including the initialisation work, can grab simply grab an IProgressMonitor from a manager class, and call progress update methods on it (like done(), percentDone(), and so on). If any Activity is visible, this causes visible progress notifications to be visible (using the Crouton library).
The actual implementation behind the IProgressMonitor uses a Handler to transfer the done(), percentDone() etc. updates onto the UI thread. Then, the manager class gets the updates via the Handler and it causes visible status updates if an Activity is visible (and has registered with the manager).
What has brought me to the above question is that when the application starts and the initialisation happens for the first time, calls on the IProgressManager don't seem to find their way through to the manager via the UI-Thread Handler until the first Activity is visible. This doesn't matter whatsoever from a functionality point of view because without a visible Activity the manager can't display anything anyway. But I am just curious about the cause.
the messages are not "lost" as you said, they are delivered, just later. That's because even thou you have have several Handler object, the queue the messages are going to is just one, the Lopper queue. And when your activity is launch, the Android system already queue-up all the other stuff it has to do in order to show the activity to the user.
On a side note: If it's not used for any UI related stuff, DO NOT PUT IT ON THE UI THREAD! Makes sense right?
Some options, might vary depending on what they're doing exactly:
use lazy initialisation, meaning, only init those components first time the user actively needs them.
create a HandlerThread with low priority to perform those operations that are not UI related. Maybe even delay them for a couple of seconds to let the whole UI be built first, before executing any of them.
edit based on your extra information:
I do not advise on the approach you're taking in building this and the reason is: that's not what Handlers are for and the Android framework have its own implementations for long running tasks and how to communicate back with the currently active Activity
"This work is a long-running task" in Android, long running tasks, specially tasks that have nothing to do with the UI, should be delegate to a Service Probably you should look into a IntentService that automatically have a HandlerThread that executes long tasks in a background thread the order they are received and auto-destroy when there's nothing more to execute.
To get update information about on going tasks that are being executed on the service there're two possible approaches.
1 - more complex, but more complete approach, You bind the Activity to the Service and direct call methods on it like setListener. That involves some ServiceConnection callbacks, but also allows a close interaction between activity and Service.
2 - a simpler unidirectional approach is to have dispatch updates to the LocalBroadcastManager and make the activity listen to them, I'll show you a quick example below:
service code, for example to send a progress update on build data structure job
Intent i = new Intent(MY_APP_UPDATE);
i.putExtra("serviceType", BUILDING_DATA_STRUCTURE);
i.putExtra("updateType", ON_UPDATE);
i.putExtra("updateValue", progress_percent);
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
then on your activity you create a BroadcastReceiver inner class and onResume/onPause you listen for updates.
private BroadcastReceiver myReceiver = new BroadcastReceiver(){
#Override public void onReceive (Context context, Intent intent){
int serviceType = intent.getIntExtra("serviceType", 0);
int updateType = intent.getIntExtra("updateType", 0);
int updateValue = intent.getIntExtra("updateValue", 0);
// here you can properly handle the updates being sure that your activity isResumed
}
}
then onResume/onPause you register/unregister
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, new IntentFilter(MY_APP_UPDATE));
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
but all that is because I like to play inside the Framework rules and builtin features as they tend to be slightly more hassle free than re-inventing the wheel.
Related
Ok first of all android is really confusing. The scenario is I have about two runnable classes which are created from a Login View and if logged in it will create another view which will have other data and even more activities can be created from there
Now I can pass the the Login view context when creating a thread for the runnable class and edit out UI elements in them like this:
((Activity)someContext).runOnUiThread(new Runnable(){
public void run()
{
TextView txtErr = (TextView) ((Activity)someContext).findViewById(R.id.errMsg);
txtErr.setText("Some message");
}
});
But the issue is there will be more activities that will be created and the runnable class is created at the time of logging in, and I can't keep passing contexts.
Is there a better way for accessing the UI elements of different activities from different threads?
P.S: the threads which will be accessing the UI elements doesn't extend Activity and are running in a separate thread.
EDIT
I think I need to make my question more clear... I am developing a client app for a messenger... The process goes this way... User clicks on login button which creates a thread in a separate class named ClientThread for handling socket connection and keeping the connection alive till the user logs out or connection drops. The ClientThread class loops till the socket is connected and whenever some data is received the data is passed to another thread in a class named ProcessDataThread which do the parsing of data and will update the UI accordingly.
Now in a response from server if the user is logged in I want to create an activity from that class and keep a context to that activity in ProcessDataThread as I will be updating UI on further responses from server. And if login fails ProcessDataThread will display a message on the main activity saying login failed, now I was able to achieve the later by passing the context from the MainActivity to the two threads when clicked on Login like this:
global_constants.clientObject = new ClientThread(this);
global_constants.clientThread = new Thread(global_constants.clientObject);
global_constants.clientThread.start();
And then from ClientThread to ProcessDataThread
global_constants.updateConversationHandler.post(new ProcessDataThread(SharedBuff, cntxt));
But how will I create more activities from a non-activity class and do all update them or find a UI element etc...
Not sure if I understand you, but it sounds like you are trying to control the view of an activity from outside of the Activity. This sounds hacky to me. I'd let each Activity manage its own UI.
A good way of doing decoupled communication between objects is the observer pattern, aka an "event bus" or "event dispatcher" system. An example of how to do this on Android is here: http://www.therealjoshua.com/2012/03/event-dispatching-sending-messages/
Basically, the code that's generating the error should dispatch a message. The Activity can listen for this message, and then update its own UI as needed.
EDIT
Thanks for the clarification. I think the observer pattern can still help here. Basically, your data processing threads shouldn't know anything about the UI. Just have them post an event for the error, optionally with additional info on the error. If you want, your event dispatcher class could even make the actual event calls on the UI thread itself using a Runnable like you showed, so that the listener can always assume that they are being called on the UI thread, if this is important for your design. This way you don't have to pass the context to the thread at all (at least not for purposes of updating the UI) - let the worker thread just be responsible for the work, and the activity can be responsible for its own UI.
Another option you could use is an android Handler (see http://developer.android.com/reference/android/os/Handler.html)
In this case, the work is still done in another thread, but the Activity receives a handleMessage callback from the thread at the appropriate time. I haven't used this myself but from the documentation it looks like it can get the job done for what you need.
In either case IMO, the responsibility for updating the UI should lie with the Activity, not the worker thread.
I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!
Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.
Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation
You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.
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!
From the Activity, I am creating a Handler to fire off my AsyncTask every 45 seconds in order to refresh the content of my ListView's DataAdapter. The AsyncTask works great and keeps the user informed on the progress through ProgressUpdates and Toast messages.
Since the thread's doInBackground is fire and forget and not re-usable, I am having to create a new instance of the AsyncTask from my Hander that is firing off every 45 seconds. The problem is when the screen is rotated and and then I get concurrent messages going off because the Hander was recreated and created a new instance of the AsyncTask, so the friendly user progress through ProgressUpdates and Toast messages is overwhelming and makes utilizing the ListView difficult.
And please don't suggest this as a solution: android:screenOrientation="portrait" is not an option.
For something that has to run so frequently, should I just be using a custom Thread and not the AsyncTask class? ToDo: Not shown, I have to update the Adapter later from the Sensor's onSensorChanged event to update bearings on for each location in the ListView, I was going to run that on a separate AsyncTask class because I don't need to notify the user everytime the device bearing has changed.
Since the AsyncThread cannot be reused, am I doing this all wrong? In short, what is the best way to have the Activity refresh the ListView and keeping off the UI thread when doing so?
The problem is when the screen is rotated and and then I get concurrent messages going off because the Hander was recreated and created a new instance of the AsyncTask.
Reason quoting from API Activity - Configuration Changes:
Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate.
So every object has a activity-scope life cycle (i.e. Handler, AsyncTask and etc. defined within your activity class) is suffered by this activity recreation. However, you can bypass this activity recreation, as stated in the later paragraph of Activity - Configuration Changes section:
In some special cases, you may want to bypass restarting of your activity based on one or more types of configuration changes. This is done with the android:configChanges attribute in its manifest. For any types of configuration changes you say that you handle there, you will receive a call to your current activity's onConfigurationChanged(Configuration) method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and onConfigurationChanged(Configuration) will not be called.
Not related to topic, but as a good practice, you should always destroy used object (Handler, AsyncTask and etc.) properly when activity is about to finish (i.e. in onDestroy() method).
For something that has to run so frequently, should I just be using a custom Thread and not the AsyncTask class?
AsyncTask is pretty handy but not suit for periodic task, I would use ScheduledExecutorService or TimerTask in this case, check out my answer here for sample code.
Can you please post a bit of your code ? It may be useful to understand where your problem is.
As york has pointed it out, you should probably use TimerTask. It seems that it suit better with what you are trying to do.
If it is the creation of a new instance of the Handler that create the probleme you can try something like this :
private Handler mHandler = null;
#Override
public void onCreate(Bundle _savedInstanceState) {
super.onCreate(_savedInstanceState);
setContentView(R.layout.my_layout);
if (mHandler == null) {
// TODO create your handler here
}
}
EDIT :
You can test _savedInstanceState == null too.
_savedInstanceState is used to save the state of the activity so turning the phone shouldn't be a problem anymore.
However, if you leave the activity and then go back to it, it will create a new handler (except if you instanciate it as a static variable).
I know how to use handlers to update UI elements such as progress bars toasts etc.
The problem I am having is when the context goes away such as the user pressing the back button or the Activity finishing for some reason. This causes my application to crash often.
I tried using getApplicationContext() (Thinking that this would be available throughout my entire application) but this did not work, ever - instead my application crashed!
I put try catch blocks around all UI update code, this works but is it necessary?
So...what is the bast way to handle this?
The problem I am having is when the
context goes away such as the user
pressing the back button or the
Activity finishing for some reason.
This causes my application to crash
often.
You will also get this, by default, if the user changes screen orientation, as the original activity is destroyed and a new one created.
I tried using getApplicationContext()
(Thinking that this would be available
throughout my entire application) but
this did not work, ever - instead my
application crashed!
The application context is useless from the standpoint of manipulating the UI.
So...what is the bast way to handle this?
In the end, what you need is for your thread to deliver an event to the right activity. Some techniques that people have used include:
Use a listener pattern (e.g., service manages the thread, activities register and unregister listeners with the service, thread invokes the listeners on key events)
Put the "current" instance of the activity in a static data member, which the thread uses to find out which one should be used (dangerous due to memory leaks and fails if you need multiple instances)
Limit background threads to ones that cache data, which the activity pulls (e.g., via polling) as needed