您的位置:首页 > 移动开发 > Android开发

实例讲解Android中AsyncTask的使用详解

2017-07-20 13:55 507 查看

——热爱开源,乐于分享

实例讲解Android中的AsyncTask的使用详解

一、单线程模型

在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在单线程模型中始终要记住两条法则:

1. 不要阻塞UI线程

2. 确保只在UI线程中访问Android UI工具包

二、为什么要使用AsyncTask?

基于单线程模型原则,我们需要将耗时操作放在UI线程以外,进行多线程处理,在Android中实现多线程任务机制有两种方式,Handler和AsyncTask。

1.Hnadler:

Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。

2.AsyncTask:

AsyncTask是android提供的一个助手类,它对Thread和Handler进行了封装,方便我们使用。Android之所以提供AsyncTask这个类,就是为了方便我们在后台线程中执
4000
行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作。在使用AsyncTask时,我们无需关注Thread和Handler,AsyncTask内部会对其进行管理,这样我们就只需要关注于我们的业务逻辑即可。

三、AsyncTask的5个回调方法及其之间的关系和作用

1.execute(Params… params):

启动执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。

2.onPreExecute():

在execute(Params… params)被调用后立即执行,一般用来在执行后台任务前对UI做一些初始化操作。

3.doInBackground(Params… params):

在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress… values)来更新进度信息。

4.onProgressUpdate(Progress… values):

在调用publishProgress(Progress… values)时,此方法才会被执行,直接将进度信息更新到UI组件上。

5.onPostExecute(Result result):

当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

在使用的时候,需注意:

1.异步任务的实例对象(new AsyncTask)必须在UI线程中创建。

2.execute(Params… params)方法必须在UI线程中调用。

3.不要手动调用onPreExecute(),doInBackground(Params… params),onProgressUpdate(Progress… values),onPostExecute(Result result)这几个方法。

4.不能在doInBackground(Params… params)中更改UI组件的信息。

四、实例详解

下面使用一个简单例子详细说明AsyncTask的具体用法:

实现的功能:点击Button,实现网络图片下载)

(直接上代码,因为我已经在代码里面把注释写的非常清楚了)

1.先看一下工程结构:



2.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.myasynctask.MainActivity">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="image test"
android:onClick="loadImage"
tools:layout_editor_absoluteX="147dp"
tools:layout_editor_absoluteY="36dp" />
</android.support.constraint.ConstraintLayout>


3.image.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="16dp"
android:layout_height="match_parent">

<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/progressbar"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</RelativeLayout>


4.MainActivity.java

package com.example.administrator.myasynctask;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

//button的点击事件,在xml中写的onClick
public void loadImage(View view){
startActivity(new Intent(this,ImageTest.class));
}
}


5.ImageTest.java

package com.example.administrator.myasynctask;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

/**
* Created by Administrator on 2017/7/14.
*/

public class ImageTest extends Activity {

private ImageView mImageView;//显示图片的ImageView
private ProgressBar mProgressBar;//圆形进度条,在XML中默认设置为隐藏的
private static String URL = "http://pic1.win4000.com/wallpaper/2/5603c62c082ca.jpg";

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);

mImageView= (ImageView) findViewById(R.id.img);
mProgressBar=(ProgressBar) findViewById(R.id.progressbar);

new MyAsyncTask().execute(URL);//启动异步线程时,所需要传递的参数,与AsyncTask<String, Void, Bitmap>定义的一致

}

//创建一个asynctask,继承自AsyncTask<String, Void, Bitmap>,用于连接网络,下载图片;
//三个参数分别是:传入的参数的类型(可变长度的参数)、后台任务执行的进度(一般用于条状progressbar,此处为圆形,不需要,故为void)、返回的结果的类型;
//在下面的几个重写方法中的参数与这三个参数是一致的、关联的;
class  MyAsyncTask extends AsyncTask<String, Void, Bitmap>{

//该方法在doInBackground之前执行,一般用于初始化操作
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);//显示进度条(默认是不显示的)
}

//该方法在doInBackground之后(即耗时操作完成)执行
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
mProgressBar.setVisibility(View.GONE);//隐藏进度条
mImageView.setImageBitmap(bitmap);
}

//该方法执行耗时操作的具体实现
@Override
protected Bitmap doInBackground(String... params) {
//获取传递进来的参数
String url=params[0];
Bitmap bitmap=null;
URLConnection connection;
InputStream is;
try {

//从网络下载图片的方法!!!!!!!!
connection =new URL(url).openConnection();//打开网络连接对象
is=connection.getInputStream();//获取连接输入流
BufferedInputStream bis=new BufferedInputStream(is);//封装输入流
bitmap = BitmapFactory.decodeStream(bis);//利用工厂方法将输入流转换为bitmap
//关闭流
is.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
//返回bitmap,与第三个参数bitmap(result)一致
return bitmap;
}
}
}


6.别忘了在AndroidManifest.xml文件中注册

<activity android:name=".ImageTest"/>


效果展示:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: