AsyncTask模拟进度下载以及AsyncTask取消

此文,仅做为个人学习Android,记录成长以及方便复习!

通过AsyncTask模拟下载进度,以及通过cancel进行状态标记,那么可以在AsyncTask中监测这样的改变,一旦当前状态改为cancelled,我们就要跳出循环,立刻结束当前操作,从而结束整个线程逻辑。

首先是一个按钮的布局文件

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/bt1"
        android:layout_gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载"/>
</LinearLayout>

在Activity实例化按钮并添加监听事件

MainActivity.java

package com.rui.pgasynctask;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.Button;

/**
 * Created by qqazl001 on 2018/3/29.
 */

public class MainActivity2 extends Activity{
    private Button bt;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt = (Button)findViewById(R.id.bt1);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //跳转下载Activity
                Intent intent = new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

添加一个布局文件,存放一个ProgressBar和TextView,显示进度和数值

activity2_main.xml

ProgressBar中设置为水平方向显示进度条 style="?android:attr/progressBarStyleHorizontal"

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

   <ProgressBar
       android:id="@+id/pb"
       style="?android:attr/progressBarStyleHorizontal"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_centerVertical="true"
       android:max="100"
       />
   <TextView
       android:id="@+id/tv1"
       android:layout_below="@+id/pb"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:textSize="30sp"/>
</RelativeLayout>

接下里了就是重头戏了

MainActivity.java

package com.rui.pgasynctask;

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

public class MainActivity extends AppCompatActivity {
    //声明ProgressDialog,TextView,MyAsyncTask
    private ProgressBar pb;
    private TextView tv1;
    private MyAsyncTask mtask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        //实例化pd和tv1
        pb = (ProgressBar)findViewById(R.id.pb);
        tv1 = (TextView)findViewById(R.id.tv1);
        //实例化内部类MyAsyncTask
        mtask = new MyAsyncTask();
        //启动异步加载
        mtask.execute();
    }
    //当Activity失去焦点的时候
    @Override
    protected void onPause() {
        //判断MyAsyncTask不为空,且状态是运行状态
        if(mtask!=null && mtask.getStatus() == AsyncTask.Status.RUNNING ){
            //AsyncTask标记为cancel状态,并不是真正地取消线程的执行。
            mtask.cancel(true);
        }
        super.onPause();
    }
    //创建一个异步加载内部类,继承AsyncTask
    public class MyAsyncTask extends AsyncTask<Void,Integer,Void>{
        //实现doInBackground方法
        @Override
        protected Void doInBackground(Void... voids) {
            //循环产生下载的效果
            for(int i=0;i<=100;i++){
                //判断是否被标记为true
                if(isCancelled()){
                    //被标记则中断循环
                    break;
                }
                //调用周期的下一个方法,传值进度
                publishProgress(i);
                //睡眠50毫秒,模拟下载
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        //展示进度
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //判断是否被标记,如果被标记则终止
            if(isCancelled()){
                return;
            }
            //进度赋值给Pd
            pb.setProgress(values[0]);
            //tv1显示进度
            tv1.setText("正在下载:"+values[0]+"%");
        }
    }
}

不等进度条满就后退再执行,会发现后面执行的进度条迟迟没有响应,为什么呢?这并非bug,而是 AsyncTask 所实行的一种机制。AsyncTask的底层是通过线程池去作用的。当一个线程没有完成的时候,后面的线程就无法开始。我们上一节课用了for()循环去执行进度条 的更新操作,必须等到for()循环结束后才会执行下一个Task。


令AsyncTask的生命周期和Activity或者Fragment的生命周期保持一致就可以了。
那要如何快速停止线程呢?
1. 在onPause()中标记取消状态:mTask.cancel(true);既然我们已经标记了cancel状态,那么可以在AsyncTask中监测这样的改变,一旦当前状态改为cancelled,我们就要跳出循环,立刻结束当前操作,从而结束整个线程逻辑。
2. 在doInBackground()方法的for()循环内添加isCancelled()对线程的状态进行判断:if(isCancelled())break;
3. 同理,在onProgressUpdate()方法中也做类似的处理:if(isCancelled())return;通过如上操作,我们就能快速停止当前线程,将处理权交给下一个AsyncTask。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值