线程池的使用(一)

一.概述

从今天开始,我们介绍一下线程中的一些知识点,我会通过具体的一些案例来告诉大家如何在实际开发中使用多线程。先看一张效果图
这里写图片描述

二.实现

我们先看看布局文件,这里只讲一下进度条以及两个控制按钮的样式是如何实现的

  <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="15dp"
            android:progressDrawable="@drawable/progressbar_selector"/>

这里我们用了一个android:progressDrawable属性,这是重点,我们看看

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape>
            <gradient
                android:endColor="#EEEEEE"
                android:startColor="#EEEEEE"/>
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <gradient
                    android:endColor="#ff5555"
                    android:startColor="#ff5555"/>
            </shape>
        </clip>
    </item>

</layer-list>

这里使用了layer-list标签,layer-list通常用在要显示层叠样式的布局文件中,我们这里的进度条刚好有两层,下面是背景,上面是进度,注意,下面这个item我们使用了clip标签,代表的意思是进行裁剪,如果不写的话是不会出来进度条变化的效果。

下面给出完整代码:

public class MainActivity extends AppCompatActivity {
    private CheckBox cbCancel;
    private ProgressBar progressBar;
    private TextView tv_info1;
    private TextView tv_info2;
    private TextView tvCancel;
    private TextView tvStart;
    private int num;
    private FutureTask futureTask;
    private final int TYPE_MSG_RUN = 1001;
    private final int TYPE_MSG_DONE = 1002;

    private android.os.Handler handler = new android.os.Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case TYPE_MSG_RUN:
                    progressBar.setProgress(msg.arg1);//设置进度显示
                    tv_info1.setText("线程计数:"+msg.arg1);
                    break;
                case TYPE_MSG_DONE:
                    tv_info1.setText("计数完成");
                    showStatus();
                    break;
            }
        }
    };
    private Thread thread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        addListener();
    }
    public void initView(){
        cbCancel = (CheckBox) findViewById(R.id.cb_cancel);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        tv_info1 = (TextView) findViewById(R.id.tv_info1);
        tv_info2 = (TextView) findViewById(R.id.tv_info2);
        tvCancel = (TextView) findViewById(R.id.tv_cancel);
        tvStart = (TextView) findViewById(R.id.tv_start);
    }
    public void initData(){
        progressBar.setProgress(0);
        progressBar.setMax(100);
    }
    public void addListener(){
        cbCancel.setOnClickListener(onClickListener);
        tvStart.setOnClickListener(onClickListener);
        tvCancel.setOnClickListener(onClickListener);
    }
    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.tv_start:
                    if(thread == null||futureTask == null||futureTask.isDone()){
                        //达到最大进度后重新开始
                        if(progressBar.getProgress() == progressBar.getMax()){
                            num = 0;
                        }
                        startThread();//当调用cancle(false)时,当前任务并不会中断,如果再次点击启动线程,将会加速任务执行速度
                        showStatus();
                    }
                    break;
                case R.id.tv_cancel:
                    if(futureTask!=null){
                        //试图取消对此任务的执行。如果任务已完成、或已取消,或者由于某些其他原因而无法取消,
                        // 则此尝试将失败。当调用 cancel 时,如果调用成功,而此任务尚未启动,则此任务将永不运行。
                        // 如果任务已经启动,则 mayInterruptIfRunning 参数,true,取消任务,中断线程,任务停止,
                        false,取消任务,不中断线程,也就是说当此参数设置为false时,即使点击了取消按钮,进度条还是会走
                        // 执行此任务的线程。此方法返回后,对 isDone() 的后续调用将始终返回 true。
                        // 如果此方法返回 true,则对 isCancelled() 的后续调用将始终返回 true。
                        futureTask.cancel(cbCancel.isChecked());//只能取消一次
                        showStatus();
                    }
                    break;
            }
        }
    };

    public void sendMsg(int num,int what){
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = num;
        handler.sendMessage(msg);
    }
    public void startThread(){
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                while (num<100) {
                    num++;
                    sendMsg(num,TYPE_MSG_RUN);
                    Thread.sleep(100);
                }
                sendMsg(num,TYPE_MSG_DONE);//完成
                return "Done" ;
            }
        };
        futureTask = new FutureTask(callable);
        thread = new Thread(futureTask);
        thread.start();
    }
    public void showStatus(){
        if(thread == null|| futureTask == null){
            return ;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("状态: ");
        sb.append("\nFutureTask isCancelled(): " + futureTask.isCancelled());
        sb.append("\nFutureTask isDone(): " + futureTask.isDone());//当调用cancell方法后,isDone始终返回true
        sb.append("\n\nThread isAlive(): " + thread.isAlive());
        sb.append("\nThread isInterrupted(): " + thread.isInterrupted());
        tv_info2.setText(sb.toString());
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (futureTask != null && !futureTask.isDone()) {
            futureTask.cancel(true);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值