I am a beginner at android/java development and I have just started learning about asynctask. I am trying to create an application that counts up (updating the ui thread with each incremental count) with a variable delay, and I am not sure how to pass the values into the asynctask, or even get it to work.
/*I have an editText (I used editText on purpose) named log, which is supposed
to be the output of the operation.
count is the number of counting up that I want the log to display.
time is the sleep delay I wish to set inbetween printing each number.*/
public class backgroundsend extends AsyncTask<String, Integer, String>{
@Override
protected String doInBackground(String... params) {
//and I want i to be the current count of the number to be displayed.
for (int i=1; i<count+1; i++){
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
log.setText(log.getText() +i);
}
});
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
}
@Override
protected void onPostExecute(String result){
log.setText(log.getText() + "Operation Ended \n\n");
}
}
Now this code does not compile properly because it wants i to be a final variable, and I don't know how to make the i in for loop into a final variable, if possible. I tried using a dummy variable and adding +1 every loop run and it still doesn't work. Additionally, when I tried to use the for loop/asynctask without the i value (a constant value) it would run but the ui thread would still hang like normal on large values. Can somebody give me insight as to what I am doing wrong, and how I should correct it? Thank you.
Couple problems.
runOnUiThread()
anywhere in AsyncTask
...it defeats the purpose. All functions of AsyncTask
run on the UI Thread
except for doInBackground()
so the idea is to do heavy work in doInBackground()
and update UI
in the other functions. onPostExecute()
expecting a String
but you are returning null
from doInBackground()
and that function passes its result
(if there should be one) to onPostExecute()
onProgressUpdate()
by calling publishProgress()
in doInBackground()
To fix this you could do something like
protected String doInBackground(String... params)
{
for (int i=1; i<count+1; i++)
{
publishProgress(i); update UI in onProgressUpdate()
Thread.sleep(time);
}
}
return "Operation Ended \n\n";
}
@Override
protected void onPostExecute(String result){
log.setText(log.getText() + result);
}
@Override
protected void onProgressUpdate(Integer... values)
{
// update UI here
}
I don't know how you are calling the task so I don't know what you are doing wrong there but you can do something like
backgroundsend myTask = new backgroundsend(); // can pass params to a constructor if needed
myTask.execute(...); // the ... is where you would put params to pass to doInBackground()
Thread.sleep() is a bad way to delay repetitions:
Why using System.Threading.Thread.Sleep() is a bad practice?
You can use a CountDownTimer:
but if I were you, I would post a delayed execution N-times since you already have an existing view (your text field):
// number of repetitions
private static final int REPETITIONS = 5;
// delay in mills
private static final int DELAY = 100;
// count
private int count;
final Runnable countingRunnable = new Runnable() {
@Override
public void run() {
if (count < REPETITIONS) {
count = count + 1;
log.postDelayed(countingRunnable, DELAY);
}
else {
// TODO call a method, notify a listener or whatnot your updates are over
}
}
};
...
// then in your place where you want to trigger the counting
log.postDelayed(countingRunnable, DELAY);
...
// and in `Activity|Fragment.onDestroy()` ensure to remove the callbacks
log.removeCallbacks(countingRunnable);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.