Android异步操作AsyncTask学习

本文介绍了Android中异步任务AsyncTask的使用,包括其泛型参数、回调方法、生命周期管理和注意事项。示例展示了如何在异步任务中加载网络图片和更新进度条,强调了在UI线程中创建和执行AsyncTask的重要性以及如何在Activity的生命周期中管理异步任务。

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

今天开始写博客,目的就是为了方便记录学习的一些要点,同时也和大家交流。
第一篇是关于Android的异步任务(AsyncTask)的。异步任务是为了在其它线程中更新UI。AsyncTask是一个抽象类,通常用于继承。
构建AsyncTask子类的泛型参数
AsyncTask是一个抽象类,通常用于被继承.继承AsyncTask需要指定如下三个泛型参数:
Params:启动任务时输入的参数类型.
Progress:后台任务执行中返回进度值的类型.
Result:后台任务执行完成后返回结果的类型.

.构建AsyncTask子类的回调方法
AsyncTask主要有如下几个方法:

doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.
onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.
onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.
onProgressUpdate:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.

onPreExecute方法会首先执行,之后执行doInBackground方法,最后执行onPostExecute方法。onProgressUpdate方法需要在doInBackground方法中手动调用。

下面展示使用异步处理加载网络图片.网络操作作为一个不稳定的耗时操作,从4.0开始就被严禁放入主线程中.所以在显示一张网络图片时,我们需要在异步处理中下载图片,并在UI线程中设置图片.

ImageTest.java
用于处理异步操作,从网络中加载图片


import java.io.BufferedInputStream;
import java.net.URL;

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


public class ImageTest extends Activity {

    private ImageView imageView;
    private ProgressBar progressBar;
    private static String URL = "http://www.deskcar.com/desktop/fengjing/2013812103350/11.jpg";//图片地址
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image);
        imageView = (ImageView)findViewById(R.id.image);
        progressBar = (ProgressBar)findViewById(R.id.progress);
        //通过AsyncTask的execute方法开启异步线程操作,传递的参数是doInBackground方法中的参数
        new MyAsyncTask().execute(URL);
    }

    //通过一个内部类实现异步操作
    class MyAsyncTask extends AsyncTask<String,Void,Bitmap>{

        /**
         * 对异步操作进行初始化操作
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            progressBar.setVisibility(View.GONE);
            imageView.setImageBitmap(bitmap);
        }

        /**
         * 进行异步操作
         * @param params
         * @return 返回AsyncTask中的第三个参数类型
         */
        @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 bfs = new BufferedInputStream(is);
                //将url对应的图像解析成Bitmap
                bitmap = BitmapFactory.decodeStream(bfs);
                is.close();
                bfs.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bitmap;
        }
    }
}

image.xml

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

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/image"/>

    <!--进度条,加载前显示,加载后隐藏-->
    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone"
        android:id="@+id/progress"/>

</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getApplicationContext(),ImageTest.class));
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.unicorn.asynctask.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Image Test"
        android:id="@+id/button"
         />
</LinearLayout>

记得配置Manifest文件,添加网络权限

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

运行效果:

主界面
异步加载图片效果
下面展示另外一个示例,通过异步操作更新进度条
ProgressBarTest.java

public class ProgressBarTest extends Activity {
    private ProgressBar progressBar;
    //可以声明为变量
    private MyAsyncTask myAsyncTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progressbar);
        progressBar = (ProgressBar)findViewById(R.id.pb);
        //初始化并执行异步操作
        myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();
    }

    class MyAsyncTask extends AsyncTask<Void,Integer,Void>{

        @Override
        protected Void doInBackground(Void... params) {
            //模拟进度更新
            for (int i = 0;i<100;i++){
                //向onProgressUpdate传递i
                publishProgress(i);
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //传递进的是数组 取第0位
            progressBar.setProgress(values[0]);
        }
    }
}

MainActivity.java中为按钮添加监听事件,个人觉得通过设置button的onclick属性来实现较好:

布局文件中的设置:
<Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ProgressBar Test"
        android:id="@+id/pgbn"
        android:onClick="progress"
        />

java文件中添加按钮监听事件只需要实现一个函数就好,代码结构更易阅读
  /**
     * 按钮的监听事件
     */
    public void progress(View view){
        startActivity(new Intent(this,ProgressBarTest.class));
    }

效果
点击ProgressBar Test

异步任务的取消:
AsyncTask是基于线程池进行实现的,当一个线程没有结束时,后面的线程是不能执行的.所以必须等到第一个task的for循环结束后,才能执行第二个task.
可以使异步任务的生命周期和Activity的生命周期保持一致。点击BACK键返回时会调用Activity的onPause()方法.如果需要取消异步任务时,我们需要在Activity的onPause()方法中将正在执行的task标记为cancel状态,在doInBackground方法中进行异步处理时判断是否是cancel状态来决定是否取消之前的task.
修改后的ProgressBarTest.java

public class ProgressBarTest extends Activity {
    private ProgressBar progressBar;
    //可以声明为变量
    private MyAsyncTask myAsyncTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progressbar);
        progressBar = (ProgressBar)findViewById(R.id.pb);
        //初始化并执行异步操作
        myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();
    }

    class MyAsyncTask extends AsyncTask<Void,Integer,Void>{

        @Override
        protected Void doInBackground(Void... params) {
            //模拟进度更新
            for (int i = 0;i<100;i++){
                if(isCancelled()){
                    break;
                }
                //向onProgressUpdate传递i
                publishProgress(i);
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if(isCancelled())
                return;
            //传递进的是数组 取第0位
            progressBar.setProgress(values[0]);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        //如果AsyncTask不为空且正在运行
        if (myAsyncTask != null && myAsyncTask.getStatus() == AsyncTask.Status.RUNNING)
            //cancel方法只是将对应的AsyncTask标记为cancel状态,并没有真正取消线程的执行
            //在线程中监测状态
            myAsyncTask.cancel(true);
    }
}

在onPause()方法中将异步线程cancel标记为true,在线程中监测cancel状态,为true时采取措施结束进程。

牢记AsyncTask.cancel()方法只是对isCanceled进行标记,并没有真正取消线程,需要将AsyncTask和Activity或者Fragment生命周期进行绑定,监测isCanceled并进行修改。

使用AsyncTask的注意事项
① 必须在UI线程中创建AsyncTask的实例.
② 只能在UI线程中调用AsyncTask的execute方法.
③ 重写的AsyncTask的四个方法是系统自动调用的,不能手动调用.
④ 每个AsyncTask只能被执行(execute方法)一次,多次执行将会引发异常.
⑤ AsyncTask的四个方法,只有doInBackground方法是运行在其他线程中,其他三个方法都运行在UI线程中,也就说其他三个方法都可以进行UI的更新操作.

第一次写博客,不好的地方希望大家多多包涵~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值