My android application has 2 activities:
In the first one (MainActivity), the user chooses some parameters and these parameters are sent to the second activity (Display).
The second activity calls a web service, and according to the chosen parameters, the web service returns a value. I use the returned value to draw a bar chart of the evolution of this value. That's why I created a timer in the second activity that I put in the onCreate() function:
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
public void run() {
finish();
startActivity(getIntent());
}
},10000, 10000);
So every 10 seconds, the second activity is called again and the bar chart is updated with the new returned value.
The problem is, after the 2nd or the 3rd execution of the timer, several identical values are returned at the same time, as if the activity was called several times. And then the application starts freezing (but doesn't close).
I'm using the charts provided by this library: http://android-graphview.org/
I've also tried using the functions provided on the above website (resetData and appendData), and also the invalidate() function, but nothing works.
Any ideas why this happens? Is my way of refreshing the activity wrong?
The way you described it:
you create a new Timer (see 2.) with every call of the second activity
The purpose of each Timer is to call the second activity (see 1.) every 10 seconds
As a result the amount of times the second activity is called as a function of time increases exponentially.
A possible solution would be to move the timer to the onCreate method of your Main Activity (and still call the second activity from it).
This way there should be exactly one Timer active at any time.
EDIT:
As commented by Marius, an Activity might not be the optimal choice. If there is no user-input and the only thing the activity does is call a webservice and return the result, a method called from your Main Activity would be sufficient.
Firstly, calling finish() and starting the activity, NOT A GOOD IDEA.
Secondly, As far as i have understood your scenario, calling an AsyncTask inside a Timer after every 10 seconds is a better way to accomplish this. Call your web service in doInBackground() and then update your UI from onPostExecute(), this way you can avoid calling finish() and relaunching your activity every 10 seconds.
Finally you are creating a new Timer instance eveytime your Activity is called, so creating a huge number of Timer instances hanging your application.
Related
I have an application with several activities, and I have a timer I start in the first activity that is presented. The problem is this:
How can I get a reference to the current activity when the timer goes off when the activity I'm currently may not be the same as the one I started the timer.
What I actually want is to have a timer traverse all my actives, show an alert dialog when it expires and the do some stuff. But because of the way android works this seems to be impossible. Does anyone has an alternative?
I've already tried:
Using an async task to access the ui thread, doesn'nt work if it is not created in the main ui thread.
Can't use a Handler, my timer is in another class
What other choice do I have?
EDIT:
I canĀ“t change any of the activities code, the timer should be decoupled enough to function when someone plugs it in the project.
Getting an instance of the current activity from the timer worker thread should work, since it would let me run stuff in the ui thread.
Implement your timer as a singleton.
Then, implement an observer pattern:
Create an interface (maybe called AlertListener) that is implemented by each Activity you want to be alerted. This interface should have a method, something like onTimerExpired(). This method should do whatever needs to be done to the activity when the timer expires.
In your timer class, also maintain a reference to the current AlertListener and a method, named something like "setCurrentActivity(AlertListener currentActivity)".
In onResume or some other method of each activity, call MyTimer.setCurrentActivity(this).
When the timer goes off, call currentActivity.onTimerExpired().
I have several Activities and each of them has its own AsyncTask which sends requests to a server and catches its responses. These days if AsyncTask is in execution I have a ProgressDialog which blocks User from navigation to another Activities. I want to get rid of the ProgressDialog and substitute it with ProgressBar view so user can switch between Activities. My concern is about the following: what if AsyncTaskFirst started in ActivityFirst and user navigates to ActivitySecond where AsyncTaskSecond is starting also, couldn't it happen the response from the first request will take ground in ActivitySecond so I'll miss it in ActivityFirst? If it is impossible, that's fine. If it is - how to handle such a case? Thank you very much in advance.
If the AsyncTask begun execution in the first Activity then it's execution of the postExecute method should be expected to affect the first Activity and not the second unless you've explicitly set it up otherwise.
I assume your AsyncTask has some kind of reference to the Activity, so it can update the progress bar.
If this is so, then all you have to do is add a method in the AsyncTask:
public void setHandler(MyTaskHandler handler) {
this.handler = handler;
}
When you start a new activity, call this method and pass on the new activity.
Then when the AsyncTask calls the Activity's update progress method, it will use the current Activity regardless of where the task was started from.
BTW: It might be better to use fragments and not activities, if it's the same component only different parts of the display. Then you do not have this problem at all, because the activity remains the same. See these guides about fragments:
http://developer.android.com/training/basics/fragments/index.html
http://developer.android.com/guide/components/fragments.html
I have three AsyncTasks in my Splash screen Activity that downloads app data for caching. I don't want to actually start the next Activity until all task's finish.
Is there an effective way of doing this?
Here is how I call my Tasks in the onCreate:
TrendingTask task = new TrendingTask(SplashActivity.this);
task.execute();
TrendingWatchingTask task2 = new TrendingWatchingTask(
SplashActivity.this);
task2.execute();
new MasterTask().execute();
They are all called, one after the other. I don't actually start the next Activity until it gets to the onPostExecute() in MasterTask. But I believe this is a gamble cause the other two may not be finished.
Note: MasterTask is an inner class while the other two are their own classes.
You can keep a global integer counter and increment it every time an AsyncTask starts(in its onPreExecute()) and decrement it in onPostExecute(). And when you launch your activity you can check if this counter is equal to zero. If it isn't - then you know you've got AsyncTasks running.
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.
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).