AsyncTask(异步任务),主要作用是处理主线程与子线程之间的通信问题。
主线程非常重要,主要用加载我们的UI界面,完成系统和我们用户之间的交互,并将交互后的结果展示给用户,因此主线程又称为UI线程。
我们不能在主线程中进行耗时操作(加载网络图片或进行数据库查询),因为会阻塞我们的UI Thread,同样我们也不能在子线程当中来操作我们的UI元素,那么如果我们想要从网络上下载一个图片,又怎么把它更新到我们的UI控件上呢,这就关系到主线程和子线程之间的通信问题了。这时我们就可以用到AsyncTask。
一般情况下,当我们需要定义一个AsyncTask时,就要定义一个类来继承这个抽象类,并实现这个抽象类中的唯一的个抽象方法doInBackground,简单的总结AsyncTask的用法就是:三个泛型,四个步骤。
三个泛型:
AsyncTask<Params,Progress,Result>
Params:这个泛型指定的是我们传递给异步任务执行时的参数的类型。(通常指定的URL路经即String类型)
Progress:这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型。(进度条的单位通常都是Integer类型)
Result:这个泛型指定的异步任务执行完后返回给UI线程的结果的类型。
我们在定义一个类继承AsyncTask类的时候,必须要指定好这三个泛型的类型,如果都不指定的话,则将其都写成void。
四个步骤:当我们执行一个异步任务的时候,其需要按照下面的4个步骤分别执行
onPreExecute():这个方法是在异步任务执行之前执行的,并且是在主线程当中执行,一般情况下,我们在这个方法里做一些UI控件的初始化动作,例如:弹出ProgressDialog
doInBackground(Params...params):在onPreExecute()方法执行完后会立即执行这个方法,它是用来处理异步任务的方法。 Android操作系统会在后台的线程池中开启一个子线程来执行我们这个方法,所以这个方法是在子线程中执行的。这个方法执行完之后,会将我们的结果发送给最后一个onPostExecute()方法,在这个方法里,我们可以从网络当中获取数据等一些耗时操作
onProgressUpdate(Progress...values):这个方法和onPreExecute方法一样都是在主线程当中执行的额,它主要是将执行的进度返回给我们的UI界面,更新我们的进度,例如:下载一张网络图片,我们要时刻显示它的进度,就可以使用这个方法来更新我们的进度。在这个方法调用之前,我们需要在doInBackground方法中调用一个publishProgress(Progress)的方法来将我们的进度时时刻刻传递给onPostUpdate方法来更新。
onPostExecute(Result...result):当我们的异步任务执行完之后就会将结果返回给这个方法,这个方法和onPreExecute,onProgressUpdate方法一样都是在主线程中操作的,我们可以将返回结果显示在UI控件上。
我们的AsyncTask抽象类只有一个抽象方法,因为,如果我们要做一个异步任务,我们必须为其开辟一个新的线程,让其完成一些操作,而在完成这个异步任务时,我们可能并不需要弹出ProgressDialog并更新进度条,也不要需要将结果更新给我们的UI界面,所以除了doInBackground方法之外的三个方法都不是必须要有的,因此我们必须要实现的方法是doInBackground方法。
在使用AsyncTask做异步任务时,必须要遵循以下原则:
- AsyncTask类必须要在UI Thread中加载,在Android Jelly_Bean版本之后这些都是自动完成的
- execute方法必须在UI Thread当中调用
- AsyncTask对象必须在UI Thread当中进行实例化
- AsyncTask任务只能被执行一次
- 不要去手动的调用onPreExecute,doInBackground,publishProgress,onProgressUpdate,onPostExecute方法,这些都是由Android系统自动调用的。
加载一张网络图片代码展示:
Activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="300dp" android:id="@+id/image_view" android:layout_centerInParent="true"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/image_button" android:layout_centerInParent="true" android:text="@string/picture" android:layout_below="@id/image_view"/> </RelativeLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bignerdranch.android.asynctask"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project for App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. --> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/> </application> </manifest>
string.xml:
<resources> <string name="app_name">AsyncTask</string> <string name="picture"> 加载一张网络图片 </string> </resources>
MainActivity.java:
package com.bignerdranch.android.asynctask; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ImageView; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.api.GoogleApiClient; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class MainActivity extends AppCompatActivity { private ImageView mImageView; private Button mButton; ProgressDialog progressDialog; private final static String IMAGE_PATH = "http://img4.imgtn.bdimg.com/it/u=3153784763,2205498087&fm=27&gp=0.jpg"; private GoogleApiClient mClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(R.id.image_view); mButton = (Button) findViewById(R.id.image_button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new MyAsyncTask().execute(IMAGE_PATH); } }); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("提示信息"); progressDialog.setMessage("正在加载,请稍候..."); progressDialog.setCancelable(false); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mClient = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build(); } public class MyAsyncTask extends AsyncTask<String, Bitmap, Bitmap> { @Override public void onPreExecute() { super.onPreExecute(); progressDialog.show(); } protected Bitmap doInBackground(String... params) { return getBitmap(); } private Bitmap getBitmap() { Bitmap bitmap = null; HttpURLConnection connection = null; InputStream inputStream = null; try { URL url = new URL(IMAGE_PATH); connection = (HttpURLConnection)url.openConnection(); connection.setDoInput(true); connection.connect(); inputStream=connection.getInputStream(); bitmap= BitmapFactory.decodeStream(inputStream); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream!=null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(connection!=null){ connection.disconnect(); } } return bitmap; } public void onProgressUpdate(Bitmap values){ super.onProgressUpdate(values); } public void onPostExecute(Bitmap result){ super.onPostExecute(result); mImageView.setImageBitmap(result); progressDialog.dismiss(); } } }
参考文献:https://www.cnblogs.com/xiaoluo501395377/p/3430542.html