Updating a chart from an ArrayList over time? - android

I have an ArrayList of values, and I would like to iterate through the ArrayList. For every new value, I would like to update the chart with that value, and then wait a set amount of time before doing the same thing to the next value.
At the moment, my log says that all of the values are being iterated over. However, on my testing device, the chart does not update until the very end; at that point, all of the values are loaded at once, so there is no desired "slideshow" effect.
When I want to start playing back the values in my ArrayList, this method is called:
public void playback(){
if(ret != null) {
for (int x = 0; x < ret.size(); x++) {
addEntry(ret.get(x));
try {
Thread.sleep(100);
} catch (Exception e){
//Do nothing
}
}
} else {
Log.d(LOG_TAG, "ret was null.");
}
}
What can I do so that the values are displayed on my chart, one after another, with a certain amount of time between each value?
Edit: Here was the solution I ended up implementing with help from Shadab Ansari:
public void playback(){
if(ret != null) {
addEntry(0);
} else {
Log.d(LOG_TAG, "ret was null.");
}
}
private void addEntry(int index) {
final int in = index;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
yVals1.get(0).setVal(ret.get(in).intValue());
RadarDataSet set1 = new RadarDataSet(yVals1, "Set 1");
// And other UI stuff
// Recursive call!
if(in < ret.size() - 1){
addEntry(in + 1);
}
}
}, 100);
}
In case it was not clear, ret was a global variable that contained the arrays that I was going to be inserting. yVals1 was an ArrayList of Entries to populate the radar chart.
The end result is that, in this example code, the chart is updated with the next value in my ArrayList every 100 milliseconds. During this time I can still zoom in/out of the chart and rotate it with no problems.

If your addEntry() performs a UI operation then let me explain your problem -
Explanation -
Android is an event based system. Something happens on the device (the screen is touched, a key is pressed, etc.) and Android raises an event. An App is notified of an event and when one occurs that it needs to respond to it does so, often running the code that you have written. Your App runs its code in a loop under the control of the Android Operating Systems (OS). This code loop is referred to as the App's thread of execution. There is only one thread and it is responsible for both running the App code and updating the display.
So the UI update does not happen immediately and your making the UI thread sleep for 100 ms every time the loop runs. And when Android tries to update the UI, you make the thread sleep which means during this time period UI thread will not do anything. And this happens till your loop finishes. After your loop ends, the final event gets executed and you will see your UI updated by the call of addEntry() with the latest value passed.
Solution -
You can use postDelayed()-
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Perform your task and it will be executed after 100 ms
}
},100);

Related

Make views visible one by one; android

I'm having trouble with making views visible. As in: they do all appear, but at the same time, whereas I would like to show them with some delay in between. Currently I have the following code, which should make it more clear:
public void performExperiment (View v) {
Log.i(TAG, "Experiment has started on view: " + v);
final ArrayList<FocusPoint> permutation = new ArrayList<>(Arrays.asList(focusPoints));
Collections.shuffle(permutation);
for (FocusPoint fp: permutation) {
try {
Thread.sleep(1000);
fp.setVisibility(ImageView.VISIBLE);
//fp.invalidate();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Sleep failed");
}
}
}
The FocusPoint-class is an extension of ImageView in Android and the method is called upon a button-click.
What needs to happen is that all the views show up in a random order on the screen, with a second between them. This code however waits for 16 seconds (the amount of views is 16) and then shows all the views at once. I tried invalidating my the view to redraw it, and I also tried to take 'fp.setVisibility(ImageView.VISIBLE)' out of the try-catch block, but both didn't work. (Of which the latter obviously doesn't work, I didn't really expect that to work, but I'm getting really desperate :P) I have been searching for hours now, and none of the StackOverflow-pages and other fora/documentation had an answer for this problem. How can I make sure that the focuspoint draws, before the loop continues to the next?
Using Thread.sleep(ms) to delay the UI thread is a very dangerous idea, and as you can see, it doesn't lead anywhere. By blocking the thread for 16 seconds, you are effectively freezing the application for that period - including any redraws and other event handling that might happen during that time. Don't ever do that.
Instead, use a Handler and its postDelayed(Runnable, ms) method to schedule visibility changes in the future. Handlers work by adding messages to the event loop, so they don't disrupt normal behavior.
Check this modified version of your code:
private static final long FP_SHOW_DELAY_MS = 1000;
private Handler handler = new Handler();
public void performExperiment (View v) {
Log.i(TAG, "Experiment has started on view: " + v);
final ArrayList<FocusPoint> permutation = new ArrayList<>(Arrays.asList(focusPoints));
Collections.shuffle(permutation);
for (int i = 0; i < permutation.size(); i++) {
final FocusPoint fp = permutation.get(i);
handler.postDelayed(new Runnable() {
#Override
public void run() {
fp.setVisibility(View.VISIBLE);
}
}, (i + 1) * FP_SHOW_DELAY_MS);
}
}

Hide custom search bar if all items in adapter are showing

The problem I have is that listView.getLastVisiblePosition always returns -1 so I can't hide the searchView. I check this right after setting the adapter and anywhere I have tried to put this it still returns -1. I didn't see in the Docs why this would be but I imagine it would return -1 if the ListView is not showing any items. However, listView.getFirstVisiblePosition() returns 0 always, even when there is more than one item showing.
I have tried both methods Here but it doesn't make a difference when getting the wrong value.
#SuppressLint("NewApi") private void setFilters(String curType, Object curFilter)
{
// initialize several lists
itemsAdapter = new ArrayAdapter<Rowdata>(this, R.layout.list_item_text, foodItems);
listView.setAdapter(itemsAdapter);
int numItems = listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
if (numItems > foodItems.length)
{ searchField.setVisibility(View.GONE); }
else
{ searchField.setVisibility(View.VISIBLE); }
}
This method is called any time a Button is pressed or text is changed that can filter through the list. So the question is why would listView.getLastVisiblePosition() always return -1 and why would listView.getFirstVisiblePosition() always return 0? No errors/exceptions, everything runs fine except for not getting the expected results. Note: itemsAdapter.getCount() returns the correct value.
Also, I have to support API >=10
Edit
If anyone needs clarification, let me know. But basically, I have an EditText I use to search through the list. I want to hide this when there aren't more items in the list than what fit on the screen. listView.getLastVisiblePosition() always returns -1
I would really like to know the cause of the original problem but if anyone has any better way of hiding the search box when items all fit on the screen, I am open to suggestions.
Update
I put a breakpoint in onItemClick() and there I get the correct values for getFirstVisiblePosition(), getLastVisiblePosition(), and listView.getChildCount(). Before this, I get 0, -1, and null respectively.
What you need to do is roughly
listview.post(new Runnable() {
public void run() {
listview.getLastVisiblePosition();
}
});
Why this way and not directly?
Android apps run in a big event loop known as the UI / main thread. Everything that is executed in there is the result of some event. For example when your Activity needs to be created that's some sort of Activity creation event. The loop will execute code that handles this event and will for example once your are considered "created" call the onCreate method. It might call more than one method within the same iteration but that's not really important.
When you setup things like the UI in any of those onSomething methods nothing is actually drawn directly. All you do is set some state variables like a new Adapter. Once you return from those on methods the system gains back control and will check what it needs to do next.
The system will for example check if the window needs to be redrawn and if so will enqueue a redraw event in the event queue which is at a later point executed by the loop. If nothing needs to be drawn it's just idle and will wait for example for touch events that are enqueued for that loop as well.
Back to your problem: By calling .setAdapter() you essentially reset all states of the ListView. And since actual updates of the ListView will only happen after you hand control back to the system you will get nothing useful out of .getLastVisiblePosition().
What needs to happen before is that ListView is instructed to be redrawn or to measure it's new size, count the amount of items it has and so on. Once it has done that it will be able to give you the required information.
.post(Runnable r) simply enqueues a Runnable into the eventqueue which is then executed by the loop once it's first in the queue.
a Runnable does not require a Thread, it's just a regular Object with a method named run() and the contract of a Runnable is simply that something (which often happens to be a Thread) can call the run() method to execute whatever you want to run. Magical loop does that.
Result of you posting a runnable is looks inn pseudo code somewhat like this:
void loop() {
yourActivity.onSomething() { loop.enqueue(runnable) }
ListView.redraw() // |
runnable.run() // <--+
}
My suggestion to resolve this problem will not be professional or light weight.
I am suggesting that you should get count of all views in listView and check every one of them are they visible.
example:
private int getIndexOfLastVisibleView(ListView view){
int count = view.getChildCount()-1;
for(int i = count ; i>=0 ; i--){
View checkedView = view.getChildAt(i);
if(checkedView.isShown()){
return i;
}
}
return -1;
}
May not be perfect but I hope that it will work.
You can refer to my answer here Strange problem with broadcast receiver in Android not exactly the same but you can get the idea why your code not working.
To make it more clear, when you set the adapter to the ListView, nothing has been drawn yet and the method getLastVisiblePosition() can only return the correct value after the listview finish drawing all of it's visible children and know which one is the last visible one.
So, the most appropriate approach I can suggest here is trigger a callback after the listView finished drawing and we get the correct value then.
The ListView with listener after drawing:
static class MyListView extends ListView {
private OnDrawCompletedListener mOnDrawCompletedListener;
public MyListView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mOnDrawCompletedListener != null) {
mOnDrawCompletedListener.onDrawCompleted();
}
}
public void setOnDrawCompletedListener(OnDrawCompletedListener listener) {
mOnDrawCompletedListener = listener;
}
public static interface OnDrawCompletedListener {
public void onDrawCompleted();
}
}
The sample code for getting last visible position
mListView.setAdapter(new EfficientAdapter(this));
//Will get -1 here
Log.e("Question-17953268",
"getLastVisiblePosition = "
+ mListView.getLastVisiblePosition());
mListView.setOnDrawCompletedListener(new OnDrawCompletedListener() {
#Override
public void onDrawCompleted() {
//Will get correct value here
Log.e("Question-17953268",
"getLastVisiblePosition = "
+ mListView.getLastVisiblePosition());
}
});
Thanks to zapl's answer I was able to get what I needed. I thought I would post the full code in case it helps anyone
listView.post(new Runnable()
{
public void run()
{
int numItemsVisible = listView.getLastVisiblePosition() -
listView.getFirstVisiblePosition();
if (itemsAdapter.getCount() - 1 > numItemsVisible)
{ searchField.setVisibility(View.VISIBLE); }
else
{
searchField.setVisibility(View.GONE);
setFilters("searchtext", "");
}
}
});

Android Chronometer, retain time state (and keep counting in background)

I have a timer that counts up from the time a user encounters that activity
I am currently using a Chronometer set during onCreate (initially started only when certain conditions are met). But I need the chronometer to keep counting upward until the app and all its views are closed (I have an "Exit" function to do that).
The problem is that the Chronometer gets reset to zero on every time I look at another tab and come back to its activity. (This has to do with the oncreate, but I dont know the way around it)
I didn't find an intuitive way to save the chronometer's state or countup in the background on its own (or to perhaps keep track of the time on my own and update the chronometer visually at a different point in time)
One idea I had was to start the Chronometer with a service and let the service keep counting , while having a textview in the existing activity update using the chronometer's current time tally as a string
any insight on a known approach to this problem be appreciated!
This is further complicated because this is an activity in a tabhost, and tabhosts call both onPause and onResume every time you load a view, so this breaks lifecycle functions.
There are a number of ways to persist the time. The easiest one I have found is to store the time in the Intent that was used to create the original activity via getIntent().putExtra("START_TIME", floatvalue). You may retrieve the value with getIntent().getFloatExtra("START_TIME", 0f). Doing it this way has a number of benefits:
It doesn't break the Activity LifeCycle and does not require a Context.
It can be passed easily between other Activities and Applicaitons.
It persists among Pauses and Stops.
It doesn't require special listeners.
It doesn't create any new objects (the Intent is the one used to create the Activity the first time).
This solution is great for persisting in a Tabbed Activity, or across Dialogs, etc. It has some limitations if leaving the Application to a more memory intensive one, but only if your Activity is destroyed (due to memory).
Because of my Tabhost, the lifecycle functions could not be relied on.
What I did was make the chronometer a static global in a central class, and added a ontabchangedlistener within my tabhost that checked to see if the tab being changed to was the tab with the chronometer. If this was true then it stores the Long value of the chronometer's current time.
tabHost.setOnTabChangedListener(new OnTabChangeListener(){
#Override
public void onTabChanged(String arg0) {
// TODO Auto-generated method stub
if(arg0.contentEquals("homeGroup"))
{
//store time in centralhelper.java
//stopWatch is of type Chronometer
//stopWatchLastTime is of type Long and is initially set to zero. Chronometer uses milliseconds to determine time, will never be zero after set
CentralHelper.stopWatchLastTime = CentralHelper.stopWatch.getBase();
}
}
});
When my homeGroup view loads, the onResume() function is called, there is a condition here to retrieve the time for the chronometer to resume counting from. Despite the fact that a tabhost will call both onPause() and onResume() in EVERY load outside of normal lifecycle functions, they still get called before onCreate()
public void onResume(){
super.onResume();
//update Chronometer with time stored in tabchangelistener
if(CentralHelper.stopWatchLastTime!=0)
CentralHelper.stopWatch.setBase(CentralHelper.stopWatchLastTime);
}
this allowed me to do a similar check in onCreate()
if(CentralHelper.stopWatchLastTime!=0)
{
CentralHelper.stopWatch.start(); //this is where it resumes counting from the base set in onResume()
}
else
{
CentralHelper.stopWatch.start();
CentralHelper.stopWatch.setBase(SystemClock.elapsedRealtime());
}
When you switch to a different activity the previous one is paused (onPause, asand so on, in attached image) when you came back to the activity it is resumed, but occasionaly when dalvik runs out of memory your Activity object can be deleted when ton showing.
If you keep your application data in the Activity instance you might loose it accidentally, please read this Activity Lifecycle http://developer.android.com/reference/android/app/Activity.html
This approach is tested and it works really well.
Try this:
Take a boolean volatile variable which will control your thread(start/stop). Take three text views, hour, min and sec text views, and remove chronometer completely. Update your UI using a Handler Write the following code.
public void timeUpdate()
{
timerThread = new Thread(new Runnable() {
#Override
public void run() {
while(continueThread){
Date newDate = new Date();
if(((newDate.getTime()) - date.getTime()) > 1000){
secondCounter = secondCounter+1;
mHandlerUpdateSec.post(mUpdateSec);
System.out.println("Inside the Theread ..."+secondCounter);
if(secondCounter > 59){
minuteCounter = minuteCounter + 1;
mHandlerUpdateMinute.post(mUpdateMinute);
secondCounter = 0;
if(minuteCounter > 59){
hourCounter = hourCounter + 1;
mHandlerUpdateHour.post(mUpdateHour);
minuteCounter = 0;
}
}
}
try{
timerThread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
}
});
timerThread.start();
}
The continueThread is a boolean volatile variable. Setting it to false will stop the thread. The timerThread is an instance of thread. There are three counters, hour, min and sec counters which will give you the latest time values. The handlers are updated as follows.
final Handler mHandlerUpdateSec = new Handler();
final Runnable mUpdateSec = new Runnable() {
public void run() {
String temp = "" + secondCounter;
System.out.println("Temp second counter length: " + temp.length());
if(temp.length() == 1)
secTextView.setText("0" + secondCounter);
else
secTextView.setText("" + secondCounter);
}
};
final Handler mHandlerUpdateMinute = new Handler();
final Runnable mUpdateMinute= new Runnable() {
public void run() {
String temp = "" + minuteCounter;
System.out.println("Temp second counter length: " + temp.length());
if(temp.length() == 1)
minTextView.setText("0" + minuteCounter);
else
minTextView.setText("" + minuteCounter);
}
};
final Handler mHandlerUpdateHour = new Handler();
final Runnable mUpdateHour = new Runnable() {
public void run() {
String temp = "" + hourCounter;
System.out.println("Temp second counter length: " + temp.length());
if(temp.length() == 1)
hourTextView.setText("0" + hourCounter);
else
hourTextView.setText("" + hourCounter);
}
};
Now, whenever you want to start the timer, set continueThread to true and call timeUpdate(). To stop it, just do continueThread = false. To start the thread again, set continueThread to true and call timeUpdate() again. Make sure you update the counters accordingly while you start/stop the timer.
You could save the start time in a sharedpreferences (or file, etc.) and establish your count-up from that (rather than starting at 0) in onResume().
Your UI may need some changes to handle the fact that you will have to reset the start time, since it could theoretically count forever.

Android 2d canvas game: FPS Jitter problem

I based my game off of the lunar lander demo, although heavily modified, and I can get around 40-50fps but the problem is it fluctuates between 40-50fps so much that it causes the moving graphics to jitter! Its very annoying and makes my game look really shitty when in fact its running at a good frame rate.
I tried setting the thread priority higher but that just made it worse... now it will fluctuate between 40-60fps...
I was thinking of limiting the FPS to about 30 so that it will be constant. Is this a good idea and does anyone else have experience or a different solution?
Thanks!
This is my run loop
#Override
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if(mMode == STATE_RUNNING){
updatePhysics();
}
doDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
private void updatePhysics() {
now = android.os.SystemClock.uptimeMillis();
elapsed = (now - mLastTime) / 1000.0;
posistionY += elapsed * speed;
mLastTime = now;
}
Don't base your game's logic (object movement, etc.) updating rate on the framerate. In other words, put your drawing and logic updating code in two separate components/threads. This way your game logic is completely independent from your framerate.
Logic updating should be based on how much time has passed since the last update (let's call it delta). Therefore, if you have an object moving at 1px/millisecond, then during each update your object should do something like this:
public void update(int delta) {
this.x += this.speed * delta;
}
So now even if your FPS lags, it won't affect your object's movement speed, since the delta will just be larger, making the object move farther to compensate (there are complications in some cases, but that's the gist of it).
And this is one way of calculating delta within your logic updating object (running in some thread loop):
private long lastUpdateTime;
private long currentTime;
public void update() {
currentTime = System.currentTimeMillis();
int delta = (int) (currentTime - lastUpdateTime);
lastUpdateTime = currentTime;
myGameObject.update(delta); // This would call something like the update method above.
}
Hope that helps! Please ask if you have any other questions; I've been making Android games myself. :)
Sample code:
Copy these two snippets (1 activity and 1 view) and run the code. The result should be a white dot smoothly falling down your screen, no matter what your FPS is. The code looks kinda complicated and long, but it's actually quite simple; the comments should explain everything.
This activity class isn't too important. You can ignore most of the code in it.
public class TestActivity extends Activity {
private TestView view;
public void onCreate(Bundle savedInstanceState) {
// These lines just add the view we're using.
super.onCreate(savedInstanceState);
setContentView(R.layout.randomimage);
RelativeLayout rl = (RelativeLayout) findViewById(R.id.relative_layout);
view = new TestView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
10000, 10000);
rl.addView(view, params);
// This starts our view's logic thread
view.startMyLogicThread();
}
public void onPause() {
super.onPause();
// When our activity pauses, we want our view to stop updating its logic.
// This prevents your application from running in the background, which eats up the battery.
view.setActive(false);
}
}
This class is where the exciting stuff is!
public class TestView extends View {
// Of course, this stuff should be in its own object, but just for this example..
private float position; // Where our dot is
private float velocity; // How fast the dot's moving
private Paint p; // Used during onDraw()
private boolean active; // If our logic is still active
public TestView(Context context) {
super(context);
// Set some initial arbitrary values
position = 10f;
velocity = .05f;
p = new Paint();
p.setColor(Color.WHITE);
active = true;
}
// We draw everything here. This is by default in its own thread (the UI thread).
// Let's just call this thread THREAD_A.
public void onDraw(Canvas c) {
c.drawCircle(150, position, 1, p);
}
// This just updates our position based on a delta that's given.
public void update(int delta) {
position += delta * velocity;
postInvalidate(); // Tells our view to redraw itself, since our position changed.
}
// The important part!
// This starts another thread (let's call this THREAD_B). THREAD_B will run completely
// independent from THREAD_A (above); therefore, FPS changes will not affect how
// our velocity increases our position.
public void startMyLogicThread() {
new Thread() {
public void run() {
// Store the current time values.
long time1 = System.currentTimeMillis();
long time2;
// Once active is false, this loop (and thread) terminates.
while (active) {
try {
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
time2 = System.currentTimeMillis(); // Get current time
int delta = (int) (time2 - time1); // Calculate how long it's been since last update
update(delta); // Call update with our delta
time1 = time2; // Update our time variables.
}
}
}.start(); // Start THREAD_B
}
// Method that's called by the activity
public void setActive(boolean active) {
this.active = active;
}
}
I am thinking there might be, not really something wrong with some of the above code, but rather an inefficiency. I am talking about this code...
// The important part!
// This starts another thread (let's call this THREAD_B). THREAD_B will run completely
// independent from THREAD_A (above); therefore, FPS changes will not affect how
// our velocity increases our position.
public void startMyLogicThread() {
new Thread() {
public void run() {
// Store the current time values.
long time1 = System.currentTimeMillis();
long time2;
// Once active is false, this loop (and thread) terminates.
while (active) {
try {
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
time2 = System.currentTimeMillis(); // Get current time
int delta = (int) (time2 - time1); // Calculate how long it's been since last update
update(delta); // Call update with our delta
time1 = time2; // Update our time variables.
}
}
}.start(); // Start THREAD_B
}
Specifically, I am thinking about the following lines...
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
It seems to me that just having the thread hang out doing nothing is a waste of valuable processing time, when in fact what you want to be doing is performing the updates, then, if the updates have taken less time than the 25 millis, then sleep the thread for the difference of what was used during the update and 25 millis (or whatever your chosen frame rate is). In this way the update will happen while the current frame is being rendered, and will be completed so the next frame update uses the updated values.
The only problem I can think of here is that some kind of syncronization will need to occur so that the current frame render does not use partially updated values. Perhaps update into a new instance of your set of values, and then make the new instance the current instance just before rendering.
I think I remember reading something in a graphics book about the goal being to perform as many updates as you can while staying within your desired frame rate, then, and only them, perform a screen update.
This of course will require one thread to drive the updates - if you use a SurfaceView, the render is controlled by this thread when you lock the canvas (in theory, according to my understanding anyway).
So, in code, it would be more like...
// Calculate next render time
nextRender = System.currentTimeInMillis() + 25;
while (System.currentTimeInMillis() < nextRender)
{
// All objects must be updated here
update();
// I could see maintaining a pointer to the next object to be updated,
// such that you update as many objects as you can before the next render, and
// then continue the update from where you left off in the next render...
}
// Perform a render (if using a surface view)
c = lockCanvas() blah, blah...
// Paint and unlock
// If using a standard view
postInvalidate();
Good luck and any feedback from anyone using this would surely help us all learn something...
rpbarbati
I think it's about Garbage collector
I would use SurfaceView instead of View if your game is action heavy. If you don't need to update the GUI rapidly then View is fine but for 2D games it's always better to use SurfaceView.
I have a similar issue, the jitter makes large object moves look uneven. Even though the "speed" is the same, different lengths of steps make the movements look jumpy.
Broody - You say a SurfaceView is beter, however, this is not true after Android 3.0 as the View is HW accelerated but the canvas returned by .lockCanvas is not.
Steven - Yes, this is likely causing poroblems, but is easy to detect.
/Jacob

How to display timer in activity?

I need to display a time duration on a few of my Activities within the application. The timer starts when one of the Activity starts.
Should I use service for the timer ?
Is this the best way ?
Or should I start thread from one of the Activity ?
I think in the use case you're describing it would be best to store time stamps (see Data Storage) and calculate the deltas for GUI use. If you need to display a real-time clock in one of your activities you can create a separate thread in that activity just to update the clock.
Well, depending on how much interface work you need to display your progress, I would start a thread within the activity and then create a timer that checks the status of the thread progress and updates the interface as needed. Services are good for background tasks that don't require a lot of interface notification/updates.
Here's an example from a project I'm currently working on (UpdateListRunnable just calls "notifyDataSetChanged()" on my list adapter. I do it multiple times in the code so I encapsulated it in a class. Also, updateHandler is just a regular Handler instance):
#Override
public void run() {
Timer updateProgressTimer = null;
UpdateItem currentItem = null;
for(int i = 0; i < items.size(); i++) {
currentItemIndex = i;
currentItem = items.get(i);
if (currentItem.isSelected() == true) {
updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
updateHandler.post(new UpdateListRunnable());
}
}, 0, 2000); // check every 2 seconds
lookupDb.downloadUpdate(currentItem);
currentItem.setUpToDate(true);
currentItem.setStatusCode(UpdateItem.UP_TO_DATE);
currentItem.setProgress(0);
updateProgressTimer.cancel();
updateHandler.post(new UpdateListRunnable());
} // end if its the database we are hosting on our internal server
} // end for loop through update items
currentItemIndex = -1;
} // end updateThread run

Categories

Resources