Reputation: 11
How can I make this more efficient, at the moment it hangs the activity, giving the following information in logcat every time the while-loop completes I assume:
I/Choreographer: Skipped 55 frames! The application may be doing too much work on its
main thread.
Basically on a while-loop it reads a string variable, modifies and splits the string into parts which are then multiplied then divided, these final values are picked up by an interface which changes the custom UI element in the activity.
This seems too heavy on the main UI thread, I was under the impression that handler.post alleviates some of this by adding to the message queue however there are skipped frames.
I've tried to convert this code into an AsyncTask however I don't understand how this code can be converted to work in AsyncTask.
EDIT: AsyncTask custom class replacing old Thread while-loop.
(Old code for reference: http://pastebin.com/Dek6uQTE)
I'm still unsure how this fits in with AsyncTask, I have added the heavy code within the doInBackground() method however readBuf.replace
and readBuf.split
cannot be resolved. I thought to put the end changed in onProgressUpdate()
as opposed to onPostExecute()
as this would keep the UI elements updated automatically.
private class PostTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
readBuf = ((MyApplication) getApplication()).getReadBuf();
}
@Override
protected Void doInBackground(Void... readBuf) {
while (readBuf.length > 4) {
readBuf.replace("V", "");
String[] parts = readBuf.split(",");
String part1 = parts[0];
String part2 = parts[1];
speed1 = Float.parseFloat(part1);
speed2 = Float.parseFloat(part2);
finalspeed1 = (speed1 * 102) / div1;
finalspeed2 = (speed2 * 602) / div1;
publishProgress();
}
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur1);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() + finalspeed1);
speedometer1.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur2);
speedometer1.onSpeedChanged(speedometer1.getCurrentSpeed() + finalspeed2);
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
Upvotes: 1
Views: 255
Reputation: 15775
You're starting a new thread which is actually just posting a new Runnable
to the UI thread (handler
is created on the UI thread), so it's not being done in the background. Here are a few tips to help with this:
Runnable
which is performing work to the handler
, just post the result and update your UI accordingly.findViewById()
in a loop or any time after creation, if possible. Get a reference to the UI element and stash it off. This method is expensive as it does a search through your view hierarchy for the matching ID.AsyncTask
just move the "work" part of your Runnable
to the doInBackground()
method and your UI updates into the onPostExecute()
method.Thread
or AsyncTask
, be sure to shutdown/cancel the work when your Activity
leaves the run state, otherwise you will encounter problems as these components are not lifecycle aware.readBuf
is actually pulling data from, so this may also need some work. If this is real-time data coming from some other source, then you may need to have the custom Thread
loop with a small yield. If using an AsyncTask
, you'll have to create a new one each time as they are one-shot operations and not intended to be used as a long running background thread.This article on AsyncTask
has more details about how it works and pitfalls.
Upvotes: 1