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

——热爱开源,乐于分享
实例讲解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这个类,就是为了方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行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"/>

效果展示:

这里写图片描述
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值