Android API之android.os.AsyncTask

本文详细介绍了Android中AsyncTask的使用方法及原理。AsyncTask允许开发者在不直接操纵线程的情况下执行后台任务,并将结果发布到UI线程。文章通过示例展示了如何定义和执行一个AsyncTask。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7android.os.AsyncTask<Params, Progress, Result>

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.

要点:AsyncTask允许执行后台操作。无需线程、句柄,AsyncTask就可以将结果发布到UI线程。

Usage

AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground), and most often will override a second one (onPostExecute.)

要点:AsyncTask必须被扩展。子类至少重写doInBackground方法,通常还会重写onPostExcute方法。

Here is an example of subclassing:

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));
         }
         return totalSize;
     }

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

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

Once created, a task is executed very simply:

 new DownloadFilesTask().execute(url1, url2, url3);
 
AsyncTask's generic types

The three types used by an asynchronous task are the following:

  1. Params, the type of the parameters sent to the task upon execution.
  2. Progress, the type of the progress units published during the background computation.
  3. Result, the type of the result of the background computation.

Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:



 private class MyTask extends AsyncTask<Void, Void, Void> { ... }
 
The 4 steps

When an asynchronous task is executed, the task goes through 4 steps:

  1. onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
  2. doInBackground, invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate step.
  3. onProgressUpdate, invoked on the UI thread after a call to publishProgress. The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
  4. onPostExecute, invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Threading rules

There are a few threading rules that must be followed for this class to work properly:

  • The task instance must be created on the UI thread.
  • execute must be invoked on the UI thread.
  • Do not call onPreExecute(), onPostExecute, doInBackground, onProgressUpdate manually.
  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)
01-01 08:11:27.038 E/StrictMode( 2641): Tried to access the API:ViewConfiguration which needs to have proper configuration from a non-UI Context:com.android.camera.app.CameraApp@32d9eff The API:ViewConfiguration needs a proper configuration. Use UI contexts such as an activity or a context created via createWindowContext(Display, int, Bundle) or createConfigurationContext(Configuration) with a proper configuration. 01-01 08:11:27.038 E/StrictMode( 2641): java.lang.IllegalAccessException: Tried to access the API:ViewConfiguration which needs to have proper configuration from a non-UI Context:com.android.camera.app.CameraApp@32d9eff 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.StrictMode.assertConfigurationContext(StrictMode.java:2296) 01-01 08:11:27.038 E/StrictMode( 2641): at android.view.ViewConfiguration.get(ViewConfiguration.java:521) 01-01 08:11:27.038 E/StrictMode( 2641): at android.view.View.<init>(View.java:5321) 01-01 08:11:27.038 E/StrictMode( 2641): at android.widget.ImageView.<init>(ImageView.java:181) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.PhotoItem.getView(PhotoItem.java:127) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.CameraFilmstripDataAdapter.getView(CameraFilmstripDataAdapter.java:151) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.widget.FilmstripView.buildViewItemAt(FilmstripView.java:850) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.widget.FilmstripView.reload(FilmstripView.java:1827) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.widget.FilmstripView.access$1300(FilmstripView.java:58) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.widget.FilmstripView$3.onFilmstripItemLoaded(FilmstripView.java:1567) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.CameraFilmstripDataAdapter.replaceItemList(CameraFilmstripDataAdapter.java:276) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.CameraFilmstripDataAdapter.access$700(CameraFilmstripDataAdapter.java:39) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.CameraFilmstripDataAdapter$QueryTask.onPostExecute(CameraFilmstripDataAdapter.java:447) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.camera.data.CameraFilmstripDataAdapter$QueryTask.onPostExecute(CameraFilmstripDataAdapter.java:379) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.AsyncTask.finish(AsyncTask.java:771) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.AsyncTask.access$900(AsyncTask.java:199) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.Handler.dispatchMessage(Handler.java:106) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.Looper.loopOnce(Looper.java:201) 01-01 08:11:27.038 E/StrictMode( 2641): at android.os.Looper.loop(Looper.java:288) 01-01 08:11:27.038 E/StrictMode( 2641): at android.app.ActivityThread.main(ActivityThread.java:7870) 01-01 08:11:27.038 E/StrictMode( 2641): at java.lang.reflect.Method.invoke(Native Method) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 01-01 08:11:27.038 E/StrictMode( 2641): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
07-14
android.os.NetworkOnMainThreadException是Android平台中的一个异常,通常是由于在主线程中执行了网络操作而引发的。 Android应用程序的UI线程(主线程)主要用于处理用户界面的更新,如响应用户的操作、刷新UI元素等。然而,在Android平台上,从Android 4.0(即API Level 11)开始,禁止在主线程中执行耗时的网络操作,以避免阻塞用户界面的响应性能。 如果在主线程中尝试进行网络操作,就会抛出NetworkOnMainThreadException异常。这是为了提醒开发者在执行网络操作时应使用其他线程,例如后台线程、AsyncTask或线程池。 为了解决这个问题,可以采取以下方式之一: 1. 使用AsyncTask:将网络操作放在AsyncTask的doInBackground()方法中执行,该方法在后台线程中运行,并在完成后通过onPostExecute()方法将结果返回给主线程。 ```java class MyTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { // 在后台线程中执行网络操作 return null; } @Override protected void onPostExecute(Void result) { // 在主线程中更新UI或处理结果 } } // 启动任务 new MyTask().execute(); ``` 2. 使用Handler:在主线程中创建一个Handler,在其中使用post()方法来将网络操作放在Runnable中执行。从而使网络操作在后台线程中运行。 ```java Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { // 在后台线程中执行网络操作 } }); ``` 无论选择哪种方式,都可以避免在主线程中执行网络操作而导致NetworkOnMainThreadException异常。这样可以确保应用程序的响应性能,并提供更好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值