使用AsyncTask完成进度条加载

AsyncTask

AsyncTask和Handler对比

AsyncTask实现的原理,和适用的优缺点

AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

使用的优点:

简单,快捷

过程可控

使用的缺点:

在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来

Handler异步实现的原理和适用的优缺点

在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

使用的优点:

l结构清晰,功能定义明确

对于多个后台任务时,简单,清晰

使用的缺点:

在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

AsyncTask实现单个进度条

首先我们得要一个布局


<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.example.asus.mytest2.ProgressActivity">

    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/sk"
        android:max="100"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始下载1"
        android:id="@+id/btn1_progress"/>



LinearLayout>

详细的步骤我写在代码中了:

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

    start.setOnClickListener(this);
    end.setOnClickListener(this);
}

/**
 * Params 启动任务执行的输入参数,比如HTTP请求的URL。它是可变型参数。 Progress 后台任务执行的百分比 Result
 * 后台执行任务最终返回的结果,比如String。 如果某个泛型参数不需要指定类型时,可将它的设置为了Void
 * 
 * @author TED
 *
 */
class MyTask extends AsyncTask {

    /**
     * 该方法将在执行实际的后台操作前被UI 线程调用。
     * 可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以中实现。
     */
    @Override
    protected void onPreExecute() {
        tv.setText("下载中。。。");
        super.onPreExecute();
    }

    /**
     * 该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作 可以调用 publishProgress方法来更新实时的任务进度
     */
    @Override
    protected String doInBackground(String... params) {
        for(int i = 0; i<100; i++){
            try {
                Thread.sleep(500L);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            publishProgress(i);
        }
        return null;
    }

    /**
     * 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI
     * 线程, 并且在界面上展示给用户.
     * 
     */
    @Override
    protected void onPostExecute(String result) {
        tv.setText("下载完成");
        super.onPostExecute(result);
    }

    /**
     * 在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        progressBar.setProgress(values[0]);
        tv.setText("下载中"+values[0]+"%");
        super.onProgressUpdate(values);
    }


    /**
     * 在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
     */
    @Override
    protected void onCancelled() {
        tv.setText("下载失败");
        super.onCancelled();
    }

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.start:

        myTask.execute("下载中");
        break;
    case R.id.end:
        myTask.cancel(true);
        break;
    default:
        break;
    }

}

AsyncTask实现进度条主要还是在于要理解每一个方法需要干什么,那么AsyncTask是否能实现两根进度条互相不干扰的进行读条呢,答案当然是肯定的

AsyncTask实现两个进度条

先来一个布局:


<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.example.asus.mytest2.ProgressActivity">

    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/sk"
        android:max="100"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始下载1"
        android:id="@+id/btn1_progress"/>

    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/sk2"
        android:max="100"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始下载2"
        android:id="@+id/btn2_progress"/>

LinearLayout>

在这里,要实现多个线程,就要好好考虑方法体中可变长度的参数,居然是可变长度,那么自然可以传入多个参数,因此就能实现同时进行其它线程的操作

package com.example.asus.mytest2;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;

public class ProgressActivity extends AppCompatActivity {

    private SeekBar progressBar1,progressBar2;
    private Button btn1, btn2;

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

        progressBar1 = (SeekBar) findViewById(R.id.sk);
        progressBar2 = (SeekBar) findViewById(R.id.sk2);
        btn1 = (Button) findViewById(R.id.btn1_progress);
        btn2 = (Button) findViewById(R.id.btn2_progress);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                btn1.setText("下载中。。。");
                btn1.setEnabled(false);
                new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,1);
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                btn2.setText("下载中。。。");
                btn2.setEnabled(false);
                new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,2);
            }
        });

    }

    class MyTask extends AsyncTask {


        @Override
        protected Integer doInBackground(Integer... values) {
            for (int i = 0; i <= 100; i+=5) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                publishProgress(i,values[0]);
            }
            return values[0];
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            switch (values[1]){
                case 1:
                    progressBar1.setProgress(values[0]);
                    btn1.setText("下载中" + values[0] + "%");
                    break;
                case 2:
                    progressBar2.setProgress(values[0]);
                    btn2.setText("下载中" + values[0] + "%");
                    break;
                default:
                    break;
            }
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Integer result) {
            switch (result){
                case 1:
                    btn1.setText("下载完成");
                    btn1.setEnabled(true);
                    break;
                case 2:
                    btn2.setText("下载完成");
                    btn2.setEnabled(true);
                    break;
                default:
                    break;
            }
            super.onPostExecute(result);
        }
    }
}

这里我们在publishProgress(i,values[0]);传入了两个参数,通过onProgressUpdate方法来判断需要进行的操作,在这里,如要要让程序知道那个是控制那个,我们则需要引入executeOnExecutor()方法,通过内部类来调用,这样就可以完成实现多个线程的实现且互不干扰

你可能感兴趣的:(安卓)