我正在阅读有关AsyncTask的文章,并尝试了下面的简单程序。但这似乎并不奏效。我该怎么做呢?

public class AsyncTaskActivity extends Activity {

    Button btn;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener((OnClickListener) this);
    }

    public void onClick(View view){
        new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            for(int i=0;i<5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

我只是试图在后台进程中5秒后更改标签。

这是我的main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:max="10"
        android:padding="10dip">
    </ProgressBar>
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Progress" >
    </Button>
    <TextView android:id="@+id/output"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace"/>
</LinearLayout>

当前回答

如果你打开AsyncTask类,你可以看到下面的代码。

public abstract class AsyncTask<Params, Progress, Result> {
    @WorkerThread
    protected abstract Result doInBackground(Params... params);
    @MainThread
    protected void onPreExecute() {
    }
    @SuppressWarnings({"UnusedDeclaration"})
    @MainThread
    protected void onPostExecute(Result result) {
    }
}

AsyncTask的特性

AsyncTask是一个抽象类 AsyncTask有3个泛型参数。 AsyncTask有doInBackground onPreExecute onPostExecute的抽象方法 doInBackground是WorkerThread(你不能更新UI) onPreExecute是主线程 onPostExecute是主线程(你可以更新UI)

例子

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    mEmailView = (AutoCompleteTextView) findViewById(R.id.email);

    AsyncTask<Void, Void, Post> asyncTask = new AsyncTask<Void, Void, Post>() {
        @Override
        protected Post doInBackground(Void... params) {
            try {
                ApiClient defaultClient = Configuration.getDefaultApiClient();
                String authorization = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODIxMzM4MTB9.bA3Byc_SuB6jzqUGAY4Pyt4oBNg0VfDRctZ8-PcPlYg"; // String | JWT token for Authorization
                ApiKeyAuth Bearer = (ApiKeyAuth) defaultClient.getAuthentication("Bearer");
                Bearer.setApiKey(authorization);
                PostApi apiInstance = new PostApi();
                String id = "1"; // String | id
                Integer commentPage = 1; // Integer | Page number for Comment
                Integer commentPer = 10; // Integer | Per page number For Comment
                Post result;
                try {
                    result = apiInstance.apiV1PostsIdGet(id, authorization, commentPage, commentPer);
                } catch (ApiException e) {
                    e.printStackTrace();
                    result = new Post();
                }
                return result;
            } catch (Exception e) {
                e.printStackTrace();
                return new Post();
            }
        }

        @Override
        protected void onPostExecute(Post post) {
            super.onPostExecute(post);
            if (post != null) {
                mEmailView.setText(post.getBody());
                System.out.print(post);
            }
        }
    };
    asyncTask.execute();
}

其他回答

移动这两条线:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

你的AsyncTask的doInBackground方法,并把它们放在onPostExecute方法。你的AsyncTask应该看起来像这样:

private class LongOperation extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(5000); // no need for a loop
        } catch (InterruptedException e) {
            Log.e("LongOperation", "Interrupted", e);
            return "Interrupted";
        }
        return "Executed";
    }      

    @Override
    protected void onPostExecute(String result) {               
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}
private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        // Do code here

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    @Override
    protected void onCancelled() {

        super.onCancelled();
        progressDialog.dismiss();
        Toast toast = Toast.makeText(
                          getActivity(),
                          "An error is occurred due to some problem",
                          Toast.LENGTH_LONG);
        toast.setGravity(Gravity.TOP, 25, 400);
        toast.show();
    }

}

更新:2020年3月

根据Android开发人员的官方文档,AsyncTask现在已弃用。

建议使用kotlin corourines代替。简单地说,它允许您以顺序风格编写异步任务。

背景/理论

AsyncTask允许你在后台线程上运行一个任务,同时将结果发布到UI线程。

用户应该始终能够与应用程序进行交互,所以这很重要 以避免阻塞主(UI)线程的任务,如 从网上下载内容。 这就是我们使用AsyncTask的原因。 它通过包装UI线程消息队列和处理程序提供了一个简单的接口,允许您发送和处理来自其他线程的可运行对象和消息。

实现

AsyncTask是一个泛型类。(它在构造函数中接受参数化类型。)

它使用以下三种泛型类型:

Params -执行时发送给任务的参数类型。

进度-在后台计算期间发布的进度单元的类型。

结果——后台计算结果的类型。

异步任务并不总是使用所有类型。要将一个类型标记为未使用的,只需使用类型Void: 私有类MyTask扩展AsyncTask<Void, Void, Void>{…}

这三个参数对应三个你可以在AsyncTask中覆盖的主要函数:

doInBackground (Params…) onProgressUpdate(进步…) onPostExecute(结果)

执行AsyncTask

调用execute(),并将参数发送给后台任务。

会发生什么

On main/UI thread, onPreExecute() is called. To initialize something in this thread. (E.g. show a progress bar on the user interface.) On a background thread, doInBackground(Params...) is called. (Params were passed via execute.) Where the long-running task should happen. Must override at least doInBackground() to use AsyncTask. Call publishProgress(Progress...) to update the user interface with a display of progress (e.g. UI animation or log text printed) while the background computation is still executing. Causes onProgressUpdate() to be called. On the background thread a result is returned from doInBackground(). (This triggers the next step.) On main/UI thread, onPostExecute() is called with the returned result.

例子

在这两个例子中,“阻塞任务”都是从网上下载的。

示例A下载图像并在ImageView中显示它,而 例B下载一些文件。

一个例子

doInBackground()方法下载图像并将其存储在BitMap类型的对象中。onPostExecute()方法获取位图并将其放置在ImageView中。

class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bitImage;

    public DownloadImageTask(ImageView bitImage) {
        this.bitImage = bitImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mBmp = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mBmp = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mBmp;
    }

    protected void onPostExecute(Bitmap result) {
        bitImage.setImageBitmap(result);
    }
}

例B

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

例B执行

new DownloadFilesTask().execute(url1, url2, url3);

我相信它是正确执行,但你试图改变UI元素在后台线程,这不会做。

修改你的调用和AsyncTask如下:

调用类

注意:我个人建议在任何执行AsyncTask线程的地方使用onPostExecute(),而不是在扩展AsyncTask本身的类中。我认为这使代码更容易阅读,特别是如果你需要AsyncTask在多个地方处理略有不同的结果。

new LongThread() {
    @Override public void onPostExecute(String result) {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}.execute("");

LongThread类(extends AsyncTask):

@Override
protected String doInBackground(String... params) {
    for (int i = 0; i < 5; i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    return "Executed";
}