Android日记之AsyncTask的基本使用

前言

第一次写文章,记录下自己新手Android路上的开发点滴,之前学过AsyncTask基本使用,记录一下,要不然老是忘记。如有发现不对的地方也请多多指教。

正文

AsyncTask是什么?

AsyncTask就是异步处理的任务,它是Handler加上线程池的封装类,线程池可以维护数量,主要是可以避免不必要的创建和开销,AsyncTask必须要在实例的主线程中创建,它的回调方法,Android也会自动的去调用,注意的是,一个AsyncTask的实例,只能调用一次的excute方法。

AsyncTask的基本使用

首先AsyncTask是一个抽象类,用于被继承,而且要指定3个泛型参数,也可以3个都指定为空。

public class MyAsyncTask extends AsyncTask<Params,Progress,Result> {

    @Override
    protected Void doInBackground(Void... voids) {
        return null;
    }
}
//Parm:启动任务时输入参数的类型
//Progress:后台任务执行中返回的进度值
//Result:后台执行完成后返回结果的类型

构建 AsyncTaskd子类的回调方法。

  • doInBackground():必须重写,异步执行后台线程将要完成的任务。
  • onPreExecute():执行后台耗时操作前被调用,一般用来完成用户一些初始化操作。
  • onPostExecute():当doInBackground方法完成后,系统会自动调用,并且会将doInBackground返回的值传递给该方法。
  • onProgressUpdate():在doInBackground方法调用publishProgress方法后,更新任务的执行进度后,就会触发该方法。

代码如下:

package com.ju.synctask;

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

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

/**
 * 项目名: SyncTask
 * 包名 com.ju.synctask
 * 文件名: ImageTest
 * 创建日期:2019/4/1
 * 描述:图片加载测试类
 */
public class ImageTest extends AppCompatActivity {

    private static final String URL = "https://bmob-cdn-23214.b0.upaiyun.com/2019/03/30/9b72512c409fc6bd806acb50a7e7c748.jpg";
    private ImageView iv;
    private ProgressBar bar;


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

        iv = findViewById(R.id.iv);
        bar = findViewById(R.id.pro);

        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute(URL);
    }


    private class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {


        @Override
        protected Bitmap doInBackground(String... strings) {
            //取出相应的参数值

            String url = strings[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
                bis.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return bitmap;
        }


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //初始化
            bar.setVisibility(View.VISIBLE);

        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //获取doInBackground的返回值,最后进行处理
            iv.setImageBitmap(bitmap);
            bar.setVisibility(View.GONE);
        }
    }

}

图片加载测试结果.png

模拟进度条测试

package com.ju.synctask;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ProgressBar;

public class PBActivity extends AppCompatActivity {


    private ProgressBar bar;
    PAsyncTask pAsyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pbactiviity);
        bar = findViewById(R.id.progress);
        pAsyncTask = new PAsyncTask();
        pAsyncTask.execute();

    }



    private class PAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            
            //通过for循环模拟进度条进度
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                publishProgress(i);
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            bar.setProgress(values[0]);
        }
    }
}

进度条测试结果

但是你这样做发现了一个问题,如果点击返回的话然后再次进入会发现进度条不动了,这其实是因为上一次的进度条任务没有完成,AsyncTask的任务要进行排队,那要怎么解决了,很简单,可以让AsyncTask和Activity的生命周期保持一次。

在Activity的声明周期添加上这个

   @Override
    protected void onPause() {
        super.onPause();
        if (pAsyncTask != null && pAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
            pAsyncTask.cancel(true);
        }
    }

再一次跑起来,发现没什么卵用啊。其实,我们通过调用cancel调用的时候,并没有吧AsyncTask的线程给停止掉,我们只是给这个AsyncTask发送了一个cancel的请求,标记为cancel的状态而已。并不是真正的取消线程执行。我们需要在doInBackground()onProgressUpdate()添加一个isCancelled()判断,来进行停止AsyncTask,这样就可以停止掉了。

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    if (isCancelled()) {
        return;
    }
    bar.setProgress(values[0]);
}

总结

AsyncTask的基本使用方法就到此为止了,需要注意的一点是AsyncTask必须要在UI线程也就是主线程中进行创建,也必须在UI线程中调用excute方法,重写的那四个方法是自动调用的。每个AsyncTask只能被执行一次,多次调用有可能会出现异常。也不能在doInBackground()方法里面更新UI,一定要在onProgressUpdate里进行更新才行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 在Android中我们可以通过Thread+Handler实现多线程通信,一种经典的使用场景是:在新线程中进行耗时...
    吕侯爷阅读 2,030评论 2 23
  • 由于Android的特性,如果要执行耗时操作,则必须方法子线程中执行。除了Thread可以开启子线程外,Andro...
    Ruheng阅读 25,691评论 6 18
  • 参考 https://www.baidu.com/link?url=QNRznJEBT25k0bpgVD3bOni...
    CodeInfo阅读 381评论 0 0
  • Android开发者:你真的会用AsyncTask吗? 导读.1 在Android应用开发中,我们需要时刻注意保证...
    cxm11阅读 2,697评论 0 29
  • 念先生好,父母年事已高,喜欢吃稀饭,在超市采购各种煮稀饭的食材,给父母煮稀饭。把水果用料理机机碎,这样父母吃水果也...
    于宏伟1472阅读 92评论 0 0