简体   繁体   English

Android Asynctask更新UI和计算

[英]Android Asynctask update UI and computation

I am a beginner at android/java development and I have just started learning about asynctask. 我是android / java开发的初学者,我刚开始学习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. 我正在尝试使用可变延迟创建一个计数(用每个增量计数更新ui线程)的应用程序,我不知道如何将值传递到asynctask,甚至让它工作。

/*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 for for循环变成最终变量。 I tried using a dummy variable and adding +1 every loop run and it still doesn't work. 我尝试使用虚拟变量并在每次循环运行时添加+1,但它仍然无效。 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. 另外,当我尝试使用for循环/ asynctask而没有i值(一个常量值)时,它会运行,但是ui线程仍然会像正常情况一样在大值上挂起。 Can somebody give me insight as to what I am doing wrong, and how I should correct it? 有人可以让我了解我做错了什么,以及我该如何纠正它? Thank you. 谢谢。

Couple problems. 夫妻问题。

  1. Don't use runOnUiThread() anywhere in AsyncTask ...it defeats the purpose. 不要在AsyncTask任何地方使用runOnUiThread() ......它会破坏目的。 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. 除了 doInBackground() 之外AsyncTask所有函数都在UI Thread上运行,因此我们的想法是在doInBackground()执行繁重的工作并在其他函数中更新UI
  2. You have onPostExecute() expecting a String but you are returning null from doInBackground() and that function passes its result (if there should be one) to onPostExecute() 你有onPostExecute()期望一个String但你从doInBackground()返回null ,并且该函数将其result (如果应该有)传递给onPostExecute()
  3. You can pass updates to onProgressUpdate() by calling publishProgress() in doInBackground() 您可以通过调用publishProgress()中的doInBackground()将更新传递给onProgressUpdate() 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: Thread.sleep()是一种延迟重复的坏方法:

Why using System.Threading.Thread.Sleep() is a bad practice? 为什么使用System.Threading.Thread.Sleep()是一种不好的做法?

You can use a CountDownTimer: 您可以使用CountDownTimer:

Android CountDownTimer Android CountDownTimer

but if I were you, I would post a delayed execution N-times since you already have an existing view (your text field): 但如果我是你,我会发布延迟执行N次,因为你已有一个现有的视图(你的文本字段):

// 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM