一个超简单的android任务列队(排队)2

一个超简单的android任务列队(排队)2

上一篇稍微粗略的写了一个任务列队的框框,这一篇主要实现任务列队中的任务超时设置,我们可以为每一个任务设置不同的超时时长。先注明本列队方法完全脱离业务,不关心你的业务怎么写,按照要求将需要的参数设置正确即可。

我们跟着上一篇文章继续扩展,LineUpTaskHelp类增加setTimeOut方法。 下面是具体实现。

package com.example.lineuppoject;

import android.text.TextUtils;
import android.util.Log;

import java.util.Iterator;
import java.util.LinkedList;

/**
 * @param <T> 任务  任务/ 需要排队的任务, 支持扩展
 * @author gongjiebin
 */
public class LineUpTaskHelp<T extends ConsumptionTask> {

    /**
     * 排队容器, 需要排队的才会进入此列表
     */
    private LinkedList<T> lineUpBeans;

    /**
     * 执行下一个任务
     */
    private OnTaskListener onTaskListener;

    public LineUpTaskHelp<T> setOnTaskListener(OnTaskListener<T> onTaskListener) {
        this.onTaskListener = onTaskListener;
        return this;
    }

    private static LineUpTaskHelp lineUpTaskHelp;

    private LineUpTaskHelp() {
        // app 只会执行一直,知道释放
        lineUpBeans = new LinkedList<>();
    }

    public static LineUpTaskHelp getInstance() {
        if (lineUpTaskHelp == null) {
            lineUpTaskHelp = new LineUpTaskHelp();
        }
        return lineUpTaskHelp;
    }

    /**
     * 加入排队
     *
     * @param task 一个任务
     */
    public void addTask(T task) {
        if (lineUpBeans != null) {
            Log.e("Post", "任务加入排队中" + task.taskNo);
           if (!chackTask()) {
                if (onTaskListener != null) onTaskListener.exNextTask(task);
            }
            lineUpBeans.addLast(task);
        }
    }


    /**
     * 设置任务超时时间。
     *
     * @param task
     */
    public void setTimeOut(T task) {

        task.setOnTimeOutLinsenet(new ConsumptionTask.OnTimeOutLinsenet() {
            @Override
            public void timeOut(ConsumptionTask task) {
                // 设置超时监听
                if (onTaskListener != null) {
                    onTaskListener.timeOut(task);
                }
            }
        });
        task.openTime(); // 打开超时等待。如果任务在规定时间未执行完成,则抛弃该任务
    }

    /**
     * 检查列表中是否有任务正在执行。
     *
     * @return true 表示有任务正在执行。false可立即执行改任务。
     */
    public boolean chackTask() {
        boolean isTask = false;
        if (lineUpBeans != null) {
            if (lineUpBeans.size() > 0) {
                for (int i = 0; i < lineUpBeans.size(); i++) {
                    if (!lineUpBeans.get(i).isResult) {
                        // 是否还有未执行的任务
                        isTask = true;
                        break;
                    }
                }
            }
        }
        return isTask;
    }


    /**
     * 得到下一个执行的计划,
     *
     * @return 返回下一个将要执行的任务, 返回null ,代表没有任务可以执行了
     */
    public T getFirst() {
        T task = null;
        if (lineUpBeans != null) {
            for (int i = 0; i < lineUpBeans.size(); i++) {
                if (!lineUpBeans.get(i).isResult) {
                    // 找到还没有未执行的任务
                    task = lineUpBeans.get(i);
                    break;
                }
            }
        }
        return task;
    }



   /**
     * 执行成功之后,删除排队中的任务。
     *
     * @param task
     */
    private void deleteTask(T task) {
        if (lineUpBeans != null && task != null) {
            deleteTaskNoAll(task.taskNo);
        }
    }


    /**
     * 删除对应计划id的所有任务
     *
     * @param planNo
     */
    public void deletePlanNoAll(String planNo) {
        if (lineUpBeans != null) {
            Iterator iterator = lineUpBeans.iterator();
            if (TextUtils.isEmpty(planNo)) return;
            while (iterator.hasNext()) {
                ConsumptionTask task = (ConsumptionTask) iterator.next();
                if (task.planNo.equals(planNo)) {
                    iterator.remove();
                }
            }
        }
    }

    /**
     * 删除对应任务id的项
     *
     * @param taskNo
     */
    public void deleteTaskNoAll(String taskNo) {
        if (lineUpBeans != null) {
            Iterator iterator = lineUpBeans.iterator();
            if (TextUtils.isEmpty(taskNo)) return;
            while (iterator.hasNext()) {
                ConsumptionTask task = (ConsumptionTask) iterator.next();
                if (task.taskNo.equals(taskNo)) {
                    iterator.remove();
                    break;
                }
            }
        }
    }


    /**
     * 外部调用, 当执行完成一个任务调用
     */
    public void exOk(T task) {
        deleteTask(task); // 删除已经执行完成的任务。
        if (lineUpBeans != null) {
            if (chackTask()) {
                // 发现还有任务
                if (onTaskListener != null) {
                    onTaskListener.exNextTask(lineUpBeans.getFirst());
                }
            } else {
                if (onTaskListener != null) {
                    onTaskListener.noTask();
                }
            }
        }
    }


    /**
     * 当第一个任务执行完成,发现列队中还存在任务, 将继续执行下一个任务
     */
    public interface OnTaskListener<T extends ConsumptionTask> {
        /**
         * 执行下一个任务
         *
         * @param task
         */
        void exNextTask(T task);

        /**
         * 所有任务执行完成
         */
        void noTask();

        /**
         * 超时未执行
         *
         * @param task
         */
        void timeOut(T task);
    }
}


ConsumptionTask类的扩展

package com.example.lineuppoject;

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.NonNull;

/**
 *
 */
public class ConsumptionTask{
    /*
       子ID,在列队中保持唯一。对应的是一条数据。
     */
    public String taskNo;


    /**
     * 父ID,通常以组的方式出现,关联一组相关的数据
     */
    public String planNo;


    /**
     * 超时时间, 定义任务的最长执行时间,0为无效时间,不能设置为负数,毫秒
     */
    public long timeOut;

    /**
     *  false:该任务未返回结果,true:该任务已经有结果了。
     */
    public boolean isResult;

    /**
     *  该任务是不是超时引起的任务失败
     */
    public boolean isTimeOut;

    public OnTimeOutLinsenet onTimeOutLinsenet;

    public void setOnTimeOutLinsenet(OnTimeOutLinsenet onTimeOutLinsenet) {
        this.onTimeOutLinsenet = onTimeOutLinsenet;
    }

    /**
     *  打开超时等待
     */
    public void openTime(){
    // 线程在执行完之后会自动关闭
        new TaskThread().setTask(ConsumptionTask.this).start();
    }



    /**
     *  监听任务是否超时
     */
    public interface OnTimeOutLinsenet{

        /**
         *  超时未执行
         * @param task
         */
        void timeOut(ConsumptionTask task);
    }
}

新增TaskThread类,此线程为记录单个任务的执行时长


package com.example.lineuppoject;

import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;

/**
 *  记录任务超时线程
 */
public class TaskThread extends Thread {

    private ConsumptionTask task;

    /**
     *
     */
    private Handler handler;

    public TaskThread(){
        handler = new Handler(Looper.getMainLooper());
    }

    public TaskThread setTask(ConsumptionTask task) {
        this.task = task;
        return this;
    }

    public ConsumptionTask getTask() {
        return task;
    }

    @Override
    public void run() {
        super.run();
        if (task.timeOut == 0) return;
         Log.e("Post", "记录当前任务,任务id:" + task.taskNo + "超时时间" + (task.timeOut / 1000) + "s");
       // handler.removeCallbacks(runnable);
        handler.postDelayed(runnable, task.timeOut);
    }


    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (!task.isResult) {
                // 设置的超时时间到了,但是还没有结果
                task.isTimeOut = true; // 是超时引起的错误。
                task.onTimeOutLinsenet.timeOut(getTask());
            }
             // 记得移除
            handler.removeCallbacks(runnable);
        }
    };

}

应用-Test

package com.example.lineuppoject;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    LineUpTaskHelp lineUpTaskHelp;

    int index = 0;

    private EditText et_time;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 文本框。
        et_time = findViewById(R.id.et_time);

        lineUpTaskHelp = LineUpTaskHelp.getInstance();

        findViewById(R.id.btn_on).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ConsumptionTask task = new ConsumptionTask();
                task.taskNo = "Task" + (index++); // 确保唯一性
                task.planNo = "No9527"; // 将数据分组, 如果没有该需求的同学,可以不进行设置
                // 开始执行任务之前,设置超时时间, 
                task.timeOut = Long.parseLong(et_time.getText().toString().trim()) * 1000; //
        

                lineUpTaskHelp.addTask(task); // 添加到排队列表中去, 如果还有任务没完成,

                et_time.setText(""); // 清空
            }
        });

        initListener();
    }



    /**
     *  注册任务监听
     */
    private void initListener(){
        lineUpTaskHelp.setOnTaskListener(new LineUpTaskHelp.OnTaskListener() {
            @Override
            public void exNextTask(ConsumptionTask task) {
                exTask(task);
            }

            @Override
            public void noTask() {
                Log.e("Post","所有任务执行完成");
            }

            @Override
            public void timeOut(ConsumptionTask task) {
                // 超时了.
                Log.e("Post","超时了,任务ID为:" + task.taskNo);
                // 具体业务逻辑根据自己需求来编写,可以重新执行,也可放弃执行,继续下一条任务
                // 检查列队, 发现任务并开始执行
                lineUpTaskHelp.exOk(task);
            }
        });
    }



    /**
     *  模拟执行任务呢
     */
    public void exTask(final ConsumptionTask task){
        new Thread(){
            @Override
            public void run() {
                super.run();
                Log.e("Post","开始执行任务" + task.taskNo + "设置的超时时间为:" + (task.timeOut/1000) + "s");
                lineUpTaskHelp.setTimeOut(task); // 启动超时。干掉这句将不会记录任务超时
                SystemClock.sleep(40*1000); // 模拟任务执行过程.这段代码就是你自己的业务代码, 这个延时40s模拟任务执行过程。
                task.isResult = true; // 执行完成,标记为已经执行(不管任务执行成功或者失败都要在任务执行完成之后赋值为true)
                if(task.isTimeOut){
                   // 。。 如果是超时引起的错误,将回调timeOut方法

                    return;
                }
                Log.e("Post","任务执行完成--------任务ID为:" + task.taskNo);
//                if(isOdd(System.currentTimeMillis())){
//                    // 模拟任务执行的结果====失败,如果一个任务失败了会导致整个计划失败,请调用此方法。
//                    Log.e("Post","任务失败了,结束掉相关联正在排队的任务组");
//                    lineUpTaskHelp.deletePlanNoAll(task.planNo);
//                }

                lineUpTaskHelp.exOk(task);
            }
        }.start();
    }

    public boolean isOdd(long i) {
        return (i & 1) == 1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值