Reputation: 337
I'm trying to update an EditText at a high rate of speed so the numbers flow more smoothly. But I've tried different combinations of techniques and objects, such as AsyncTask, Thread->Runnable with a handler, Timer->TimerTask with a handler, and no matter how long I set the timing for, it doesn't seem to get any better than approximately 1 second.
I'm thinking that it may be that fact that it is having to travel through the message pump, but I can't be sure. Does anyone have any idea how I could get an update frequency of at least 250 to 500 milliseconds? Higher frequency would be preferable, but that would do.
Update 2: I commented out everything but the count++; and I update one of the edit texts with this value and it is indeed updating very fast. So something that is happening in updateUi() is slowing it down. I just don't know what.
Update 1: I switched real-time usage of SharedPreferences which I was using to test with primitives just in case that was part of the problem. The performance appears to be the same. The only think that happens on a regular basis is an updateUi() function which runs on a timer. The code is below, and this is what I'm expecting to update quickly, but doesn't:
private void updateUi() {
lastDate = cal;
cal = Calendar.getInstance();
synchronized(cal) {
//if the current date is greater than the last stored date
if(compareDates(cal, lastDate) > 0 && count == 0) {
//disable timer
calorieTimer.cancel();
//dereference timer...probably not necessary
calorieTimer = null;
double bankBmr = currentBmr.getBMR() *
activityLevelMultipliers[activityLevelSpinner.getSelectedItemPosition()];
metrics.calorieBank += (int)bankBmr - metrics.caloriesEaten;
prefsEditor.putInt("CALORIE_BANK", metrics.calorieBank);
prefsEditor.putInt("CALORIES_EATEN", 0);
prefsEditor.commit();
metrics.caloriesEaten = 0;
//update lastDate to prevent multiple calorie banking
lastDate = cal;
count++;
Log.e("updateUi()", "count #" + count);
//set up timer again
setupCalorieTimer();
}
caloriesEatenEditText.setText("" + metrics.caloriesEaten);
caloriesRemainingEditText.setText(String.format("%d", (int)activeBmr - metrics.caloriesEaten));
bankEditText.setText("" + metrics.calorieBank);
estimatedWeightEditText.setText(String.format("%.2f", metrics.currentWeight - metrics.calorieBank / 3500.0)) ;
//update the time
time.setToNow();
//update calories available
caloriesAvailableEditText.setText(
String.format("%.2f", activeBmr * percentageOfDay(time) - metrics.caloriesEaten));
} //End synchronized(cal)
} //End updateUi()
private void setupCalorieTimer() {
//create handler to post update back to ui thread
final Handler handler = new Handler();
calorieTimer = new Timer();
calorieTimer.schedule(new TimerTask() {
@Override
public void run() {
//post to ui thread
handler.post(new Runnable() {
@Override
public void run() {
updateUi();
}
});
}
}, 0, 50);
}
Upvotes: 1
Views: 1858
Reputation: 337
It turned out that a function I didn't initially list was using the android.text.format.Time object which only has 1 second resolution. So it wasn't even poor performance, it was just that the object only elapsed once per second so it couldn't possibly update any faster. Below are the first function that caused the false alarm, and the second one was the "fix". Hopefully this will help anyone who mistakenly thinks poor performance was the culprit like I did.
//"caused" the problem
private double percentageOfDay(Time time) {
//factor the hour
double percentage = time.hour / 24f;
//factor the minute
percentage += time.minute / 1440f;
//factor the second
percentage += time.second / 86400f;
return percentage;
}
//This fixed the problem
private double percentageOfDay(Calendar cal) {
//factor the hour
double percentage = cal.get(Calendar.HOUR) / 24f;
//factor the minute
percentage += cal.get(Calendar.MINUTE) / 1440f;
//factor the second
percentage += cal.get(Calendar.SECOND) / 86400f;
//factor the millisecond
percentage += cal.get(Calendar.MILLISECOND) / 86400000f;
return percentage;
}
Upvotes: 1
Reputation: 5320
I can not reproduce this problem. With the following code updates are really fast for example (blurringly fast on a low-end tablet):
package com.mycompany.myapp42;
import android.app.*;
import android.os.*;
import android.widget.*;
import java.text.*;
import java.util.*;
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView tv = (TextView) findViewById(R.id.textView);
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
tv.setText(new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()));
}
});
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
}
}
}).start();
}
}
EDIT
There are performance problems for me too if the soft keyboard (SwiftKey) is visible.
Upvotes: 1
Reputation: 10785
there is no suppose to be any problem updating in high frequency a EditText
using Handler + delayed Runnable
or AasyncTask
with onProgressUpdate()
callback.
I can tell you that I did it lot's of times, with interval of 30-100 milliseconds, and it worked great.
that's what leading me to believe you are doing something else wrong. please post your code.
my feeling is that you are performing other code that blocks the UI thread for not reasonable amount of time (more then few milliseconds), and because of that - the part of the code that running your EditText
update on the UI thread is limited. blocking the main thread usually happens when performing in it IO file operations, database writings, image decodings or other heavy calculations, so if you have one of those on the main thread - they would be the blame.
Upvotes: 1
Reputation: 13515
try AsyncConnector from df4android, it passes messages pretty fast.
Upvotes: 1