今天看啥  ›  专栏  ›  xujl

RxTask-快捷切换线程,告别到处创建handler

xujl  · 掘金  ·  · 2019-09-15 15:28
阅读 17

RxTask-快捷切换线程,告别到处创建handler

RxTask,基于线程池+handler封装工具。从此告别到处创建handler,远离到处创建线程无法管理。
已迁移到Androidx

早期的版本介绍:
RxTask初版上篇
RxTask初版下篇

项目地址 我的Github 我的码云

集成方式: implementation 'com.xujl:task:1.0.1'

初始化

 //默认初始化,默认初始化后核心线程数为cpu核心数X4
 RxExecutor.getInstance().init();
 //自定义核心线程数量进行初始化
 RxExecutor.getInstance().init(32);
 //完全自定义工具线程池
 RxExecutor.getInstance().init(ExecutorService);
 //关闭log输出,默认为开启
 RxExecutor.getInstance().setDebug(false);
复制代码

如何使用?

场景1

子线程任务,执行完毕结果数据返回给主线程显示
RxExecutor.getInstance()
                .executeTask(new Task<String>(){
                    @Override
                    public void run (Emitter<String> emitter) throws Exception {
                        super.run(emitter);
                        //当前为子线程
                        //模拟子线程任务
                        Thread.sleep(1000);
                        //任务结束发送数据到主线程
                        emitter.next("任务执行结果数据");
                    }

                    @Override
                    public void onNext (String data) {
                        super.onNext(data);
                        //当前为主线程
                        //显示子线程执行结果
                        textView.setText(data);
                    }
                });
复制代码

场景2

子线程任务,不关心任务结果,只关心完成时机
  RxExecutor.getInstance()
                .executeTask(new Task<String>() {
                    @Override
                    public void run (Emitter<String> emitter) throws Exception {
                        super.run(emitter);
                        //当前为子线程
                        //模拟子线程任务
                        Thread.sleep(1000);
                        //任务结束
                    }

                    @Override
                    public void onFinished () {
                        super.onFinished();
                        //当前为主线程
                        // 执行主线程逻辑
                    }
                });
复制代码

场景3

单纯执行一个子线程任务,不关心任务结果,也不需要在任务结束后有任何操作
  RxExecutor.getInstance()
                .executeTask(new Task<String>() {
                    @Override
                    public void run (Emitter<String> emitter) throws Exception {
                        super.run(emitter);
                        //当前为子线程
                        //模拟子线程任务
                        Thread.sleep(1000);
                        //任务结束
                    }
                });
复制代码

场景4

执行一个普通子线程而非task
    RxExecutor.getInstance()
                        .executeRunnableTask(new Runnable() {
                            @Override
                            public void run () {
                                //当前为子线程
                                //模拟子线程任务
                                Thread.sleep(1000);
                                //任务结束
                            }
                        });
复制代码

场景5

执行的任务绑定生命周期,界面销毁后,不再回调

在bindLife方法中完成绑定,生命周期结束后,onFinished和onNext将不会再回调。

    private RxLifeList mBindLife = new RxLifeList();
    private void test(){
        RxExecutor.getInstance()
                .executeTask(new Task<String>() {
                    @Override
                    public void run (Emitter<String> emitter) throws Exception {
                        super.run(emitter);
                        //当前为子线程
                        //模拟子线程任务
                        Thread.sleep(2000);
                        //任务结束
                    }

                    @Override
                    public void onNext (String data) {
                        super.onNext(data);

                    }

                    @Override
                    public void onFinished () {
                        super.onFinished();
                        //当前为主线程
                        // 执行主线程逻辑
                    }

                    @Override
                    public void bindLife (RxLife rxLife) {
                        super.bindLife(rxLife);
                        mBindLife.add(rxLife);
                    }
                });
    }
    @Override
    protected void onDestroy () {
        if (mBindLife != null) {
            mBindLife.onDestroy();
        }
        super.onDestroy();
    }
复制代码

场景6

当前处于某个子线程任务中,需要主线程中显示数据
//其他子线程中
        new Thread(new Runnable() {
            @Override
            public void run () {
                //模拟子线程任务
                Thread.sleep(1000);
                //切换回主线程进行逻辑
                RxExecutor.getInstance()
                        .executeUiTask(new Task() {
                            @Override
                            public void onlyRunUiTask () {
                                super.onlyRunUiTask();
                                //执行主线程逻辑
                            }
                        });
            }
        }).start();
复制代码

场景7

任务执行失败,进行重试

使用 TaskBuilder.create().setRetryMaxCount(3)传入task构造器即可实现重试功能,方法参数为最大重试次数,传入 TaskRetry.INFINITE可实现无限重试(通常不建议这么做!)。
Task默认配置为失败后不重试
任务失败后会回调onError方法并返回具体错误,如果没有配置重试,进入onError的Task将结束生命周期,不再回调onFinished或者onNext方法。

RxExecutor.getInstance()
                .executeTask(new Task<String>(
                        //配置失败重试
                        TaskBuilder.create()
                                .setRetryMaxCount(3)
                ) {
                    @Override
                    public void run (Emitter<String> emitter) throws Exception {
                        super.run(emitter);
                        //当前为子线程
                        //模拟子线程任务
                        Thread.sleep(1000);
                        //任务结束
                    }

                    @Override
                    public void onError (Exception e) {
                        super.onError(e);
                        //任务出错
                    }

                    @Override
                    public void onFinished () {
                        super.onFinished();
                        //当前为主线程
                        // 执行主线程逻辑
                    }
                });
复制代码

场景8

任务组

任务组是一种比较不常见的场景,比如开启双线程分别写入两个文件到内存卡,并且两个文件完成写入后退出界面。这时候就可以使用任务组概念进行

RxExecutor.getInstance()
                .executeTaskGroup(GroupTaskBuilder.create()
                        .setResultTask(new GroupResultTask() {

                            @Override
                            public void oneTaskComplete (Object tag, Object result) {
                                result("任务" + tag.toString() + "执行结束,数据为:" + result, R.color.task_color_4);
                            }

                            @Override
                            public void allTaskComplete (HashMap<Object, Object> resultMap) {
                                StringBuilder result = new StringBuilder();
                                for (Object o : resultMap.keySet()) {
                                    result.append(o.toString());
                                    result.append(":");
                                    result.append("" + resultMap.get(o));
                                }
                                result("组任务全部完毕,数据为:" + result.toString(), R.color.task_color_4);
                            }
                        })
                        .setGroupStrategy(GroupTaskStrategy.ALL_COMPLETE)
                        .addGroupTask(mGroupTask1)
                        .setResultTag(1)
                        .addGroupTask(mGroupTask2)
                        .setResultTag(2)
                        .addGroupTask(mGroupTask3)
                        .setResultTag(3)
                        .build());
复制代码

GroupResultTask是用来监控任务组执行结果的,每个任务执行完毕后会回调一次oneTaskComplete,所有任务执行完毕后会回调一次allTaskComplete,两个方法的参数列表返回了单个任务执行的数据结果,通过配置的tag进行判断,当然如果你不关心执行结果数据则可以不必调用setResultTag给每个任务设置tag。
任务组的执行模式有三种,通过setGroupStrategy方法进行设置(使用默认模式可以不调用这个方法):

/**
     * 默认模式
     * 全部完成模式,全部任务执行完毕后
     * 回调结果
     * 使用此模式,如果组任务配置了失败
     * 重试,则最终回调会等待组任务重试成功
     * 组任务配置了任务重试会阻塞结果回调时机
     */
    public static final int ALL_COMPLETE = 0;
    /**
     * 错误退出模式
     * 一个组任务发生错误则暂停其他任务
     * 并不再继续
     */
    public static final int ERROR_EXIT = 1;
    /**
     * 错误忽略模式
     * 一个任务发生的错误将会被忽略
     * 其他任务正常执行,并待其他任务执行后
     * 继续后续任务,使用此模式会忽略任务重试功能
     * 组任务配置了任务重试不会阻塞结果回调时机
     */
    public static final int ERROR_IGNORE = 2;
复制代码

需要注意的是ALL_COMPLETE和ERROR_IGNORE的阻塞区别,主要来源于子任务的重试策略对他们产生的不同影响。

如果你的任务组中,有一个是必要的(必须完成,不完成会影响后续逻辑),其他是非必要的(顺便执行的任务,不关心是否成功),该怎么办?
不用担心,RxTask可以在组策略下配置单个任务的策略,比如下面的示例,任务1和3为非核心逻辑,2为核心逻辑,那么只需要如下配置即可保证任务1和3失败后对最后的任务组完成回调不产生影响。

RxExecutor.getInstance()
                .executeTaskGroup(GroupTaskBuilder.create()
                        .setResultTask(new GroupResultTask() {

                            @Override
                            public void oneTaskComplete (Object tag, Object result) {
                                result("任务" + tag.toString() + "执行结束,数据为:" + result, R.color.task_color_4);
                            }

                            @Override
                            public void allTaskComplete (HashMap<Object, Object> resultMap) {
                                StringBuilder result = new StringBuilder();
                                for (Object o : resultMap.keySet()) {
                                    result.append(o.toString());
                                    result.append(":");
                                    result.append("" + resultMap.get(o));
                                }
                                result("组任务全部完毕,数据为:" + result.toString(), R.color.task_color_4);
                            }
                        })
                        .setGroupStrategy(GroupTaskStrategy.ALL_COMPLETE)
                        //非核心业务,可以允许失败
                        .addGroupTask(mGroupTask1)
                        .setStrategy(GroupTaskStrategy.ERROR_IGNORE)
                        .setResultTag(1)
                        //核心业务,必须成功才进行下一步
                        .addGroupTask(mGroupTask2)
                        .setResultTag(2)
                        //非核心业务,可以允许失败
                        .addGroupTask(mGroupTask3)
                        .setStrategy(GroupTaskStrategy.ERROR_IGNORE)
                        .setResultTag(3)
                        .build());
复制代码

使用单任务策略需要注意以下几点
首先,单任务的执行策略仅在任务组策略为GroupTaskStrategy.ALL_COMPLETE时才有效。
其次,任务组策略为GroupTaskStrategy.ALL_COMPLETE且没有配置单任务策略时,需要小心任务阻塞的处理,因为在此模式下,任何一个子任务执行失败都会造成你的后续逻辑执行不到,所以需要考虑每个任务失败时的处理逻辑。子任务出错参考前面Task任务出错时的情况。
最后,在activity中使用任务组时请务必绑定生命周期,以免出现内存泄漏问题。

场景9

多种类型数据结果

一个子线程任务过程中可能产生不同结果或者多个结果,那么可以采用下面的写法(注意使用 emitter.objNext发射数据,用onObjNext接收数据),此方法可以用来控制多种类型或者多个步骤的子线程任务,每种类型或者步骤识别使用code来进行

 RxExecutor.getInstance()
                .executeTask(new Task<Object>() {
                    @Override
                    public void run (Emitter<Object> emitter) throws Exception {
                        super.run(emitter);
                        Thread.sleep(1000);
                        //执行结果数据类型1
                        emitter.objNext("数据1", 1);
                        Thread.sleep(1000);
                        //执行结果数据类型2
                        emitter.objNext(222, 2);
                        Thread.sleep(1000);
                        //执行结果数据类型3
                        emitter.objNext(new Bundle(), 3);
                    }

                    @Override
                    public void onObjNext (int code, Object obj) {
                        super.onObjNext(code, obj);
                        switch (code) {
                            case 1:
                                //处理数据类型1
                                break;
                            case 2:
                                //处理数据类型2
                                break;
                            case 3:
                                //处理数据类型3
                                break;
                            default:

                                break;

                        }
                    }
                });
复制代码

场景10

常用子任务封装

以下三种类型均支持绑定生命周期,绑定生命周期后,生命周期结束,将不再回调

倒计时
  RxExecutor.getInstance()
                .executeTask(new RxHelper.CountDownTask(60*1000,1000) {
                    @Override
                    public void count (long time) {
                        
                    }
                });
复制代码
延时任务
 RxExecutor.getInstance()
                .executeTask(new RxHelper.DelayTask(60*1000) {

                    @Override
                    public void timeOver () {
                        
                    }
                });
复制代码
循环任务

-1表示无限循环

   RxExecutor.getInstance()
                .executeTask(new RxHelper.RecycleTask(1000,-1) {
                    @Override
                    public void count (int count) {
                        
                    }
                });
复制代码



原文地址:访问原文地址
快照地址: 访问文章快照