AsyncTask
异步任务,从字面上来说,就是在我们的UI主线程运行的时候,异步的完成一些操作。AsyncTask允许我们的执行一个异步的任务在后台。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的UI线程来更新我们的UI控件。通过AsyncTask我们可以轻松的解决多线程之间的通信问题。
3个泛型,4个步骤
3个泛型
class MyAsyncTask extends AsyncTask<Params,Progress,Result>
- Params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型
- Progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型
Result: 这个泛型指定的异步任务执行完后返回给UI线程的结果的类型
4个步骤
- onPreExecute(): 这个方法是在执行异步任务之前的时候执行,并且是在UI Thread当中执行的,通常我们在这个方法里做一些UI控件的初始化的操作,例如弹出要给ProgressDialog
- doInBackground(Params... params): 在onPreExecute()方法执行完之后,会马上执行这个方法,这个方法就是来处理异步任务的方法,Android操作系统会在后台的线程池当中开启一个worker thread来执行我们的这个方法,所以这个方法是在worker thread当中执行的,这个方法执行完之后就可以将我们的执行结果发送给我们的最后一个 onPostExecute 方法,在这个方法里,我们可以从网络当中获取数据等一些耗时的操作
- onProgressUpdate(Progess... values): 这个方法也是在UI Thread当中执行的,我们在异步任务执行的时候,有时候需要将执行的进度返回给我们的UI界面,例如下载一张网络图片,我们需要时刻显示其下载的进度,就可以使用这个方法来更新我们的进度。这个方法在调用之前,我们需要在 doInBackground 方法中调用一个 publishProgress(Progress) 的方法来将我们的进度时时刻刻传递给 onProgressUpdate 方法来更新
onPostExecute(Result... result): 当我们的异步任务执行完之后,就会将结果返回给这个方法,这个方法也是在UI Thread当中调用的,我们可以将返回的结果显示在UI控件上
上课实例:
package com.example.handerdemo;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity {
TextView textView;
//Handler handler;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
//handler = new MyHandler(this);
}
public void download(View v){
new MyAsyncTask().execute(0);
// Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
// Log.d(TAG, "run: "+Thread.currentThread().getName());
//
// });
// thread.start();
}
// static class MyHandler extends Handler{
// private WeakReference<MainActivity> activityWeakReference;
//
// public MyHandler(MainActivity activity) {
// this.activityWeakReference = new WeakReference<>(activity);
// }
//
// @Override
// public void handleMessage(Message msg) {
// Log.d(TAG, "handleMessage: "+msg);
// super.handleMessage(msg);
// String str = "Percent"+msg.what;
// activityWeakReference.get().textView.setText(str);
// }
// }
class MyAsyncTask extends AsyncTask<Integer,Integer,Integer>{
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.d(TAG, "onPostExecute: thread will run!!");
Log.d(TAG, "onPostExecute: "+Thread.currentThread().getName());
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
Log.d(TAG, "Download finished!!"+integer);
Log.d(TAG, "onPostExecute: "+Thread.currentThread().getName());
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
textView.setText("Percent"+values[0]);
Log.d(TAG, "onProgressUpdate: "+Thread.currentThread().getName());
}
@Override
protected Integer doInBackground(Integer... integers) {
Log.d(TAG, "doInBackground: "+Thread.currentThread().getName());
for(int i=0;i<=100;i++){
try {
Thread.sleep(100);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
}
}
通过AsyncTask来从网络上下载一张图片,并更新到我们的ImageView控件上
布局文件
<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:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:scaleType="fitCenter"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/imageView"
android:layout_centerHorizontal="true"
android:layout_marginTop="41dp"
android:text="从网络上下载一张图片" />
</RelativeLayout>
网络权限开启
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiaoluo.android_asynctast"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<!-- 授权手机能够访问网络 -->
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.xiaoluo.android_asynctast.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.example.externalfile;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityManagerCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class MainActivity extends Activity
{
private Button button;
private ImageView imageView;
private ProgressDialog progressDialog;
private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg";
// private final String IMAGE_PATH2 = "http://ww2.sinaimg.cn/mw690/69c7e018jw1e6hd0vm3pej20fa0a674c.jpg";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
imageView = (ImageView)findViewById(R.id.imageView);
// 弹出要给ProgressDialog
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("提示信息");
progressDialog.setMessage("正在下载中,请稍后......");
// 设置setCancelable(false); 表示我们不能取消这个弹出框,等下载完成之后再让弹出框消失
progressDialog.setCancelable(false);
// 设置ProgressDialog样式为水平的样式
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try {
URL url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556794481489&di=c538bd5bb50824fdebb55e1a7012af45&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fc5fe5eec412410778a4b926970f61a22a871f34e.jpg");
new MyAsyncTask().execute(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
/**
* 定义一个类,让其继承AsyncTask这个类
* Params: String类型,表示传递给异步任务的参数类型是String,通常指定的是URL路径
* Progress: Integer类型,进度条的单位通常都是Integer类型
* Result:byte[]类型,表示我们下载好的图片以字节数组返回
* @author xiaoluo
*
*/
public class MyAsyncTask extends AsyncTask<URL, Integer, byte[]>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
// 在onPreExecute()中我们让ProgressDialog显示出来
progressDialog.show();
}
@Override
protected byte[] doInBackground(URL... urls)
{
byte[] image = new byte[]{};
for(int i=0;i<urls.length;i++) {
URL url = urls[i];
try {
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int size = urlConnection.getContentLength();//图片文件的总长度
//publishProgress(i, size, 0);
try {
// File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "" + i + ".jpg");
//FileOutputStream outputStream = new FileOutputStream(file);
int len = -1;
int totalLen = 0;//每次读取后累加的长度
byte[] bytes = new byte[1024];//每次读取1024个字节
while ((len = inputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, len);
totalLen = totalLen + len;
int progress = (int)(((float)totalLen/(float)size) * 100);
publishProgress(progress);
Thread.sleep(1);
}
image = byteArrayOutputStream.toByteArray();
inputStream.close();
byteArrayOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return image;
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
// 更新ProgressDialog的进度条
progressDialog.setProgress(values[0]);
}
@Override
protected void onPostExecute(byte[] result)
{
super.onPostExecute(result);
// 将doInBackground方法返回的byte[]解码成要给Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
// 更新我们的ImageView控件
imageView.setImageBitmap(bitmap);
// 使ProgressDialog框消失
progressDialog.dismiss();
}
}
}
参考博客:https://www.cnblogs.com/xiaoluo501395377/p/3430542.html