关于android:XTask-一个拓展性极强的Android任务执行框架

3次阅读

共计 8362 个字符,预计需要花费 21 分钟才能阅读完成。

背景

很早之前接触了 RxJava 的工作流操作, 感觉这种将简单业务流通过一个个操作符拆解开来, 造成一条条条理清晰的 function, 让人写起来直呼过瘾. 其实这就是责任链模式的一种利用.

然而 RxJava 的性能切实是太强大了, 如果仅仅是应用它来解决这些业务流我感觉还是有些大材小用了.

之前也做过一段时间的利用性能优化, 其中当然就包含利用冷启动优化, 两头有波及过启动器的概念, 过后也查阅了一些现有的开源框架, 也应用过其中一些, 然而总感觉并不是很好用, 用起来不是很棘手.

作为一名资深 Android 开源框架卷王, 过后我脑海里就萌生一种想法, 为啥我不本人写一个工作流执行的框架呢? 想到这, 我就抽出了我的一部分业余时间(女朋友都不陪了), 撸出了这个 XTask 框架, 自我感觉十分 nice, 在这分享给大家.

简介

XTask 是一个拓展性极强的 Android 工作执行框架。

可自在定义和组合工作来实现你想要的性能,尤其实用于解决简单的业务流程,可灵便增加前置工作或者调整执行程序。例如:利用的启动初始化流程。

我的项目地址

  • github: https://github.com/xuexiangjys/XTask
  • gitee: https://gitee.com/xuexiangjys/XTask

特色

  • 反对 6 种线程类型形式执行工作。
  • 反对工作链中各工作的执行线程调度和管制。
  • 反对快捷工作创立,同时反对自定义工作。
  • 反对串行和并行等组工作。
  • 反对工作间数据共享。
  • 反对自由组合工作执行。
  • 反对工作链执行勾销。
  • 反对勾销所有工作链和指定名称的工作链。
  • 反对工作链调用程序记录和查问。
  • 反对自定义工作执行的线程池。

设计思维

框架主体应用责任链的设计模式,辅以建造者模式、工厂模式、适配器模式、组合模式、外观模式以及代理模式来实现。

组成构造

  • 工作链ITaskChainEngine:工作链执行引擎,负责兼顾调度各工作步骤。
  • 工作步骤ITaskStep:负责具体任务逻辑解决。
  • 数据存储仓库IDataStore:存放数据的仓库,次要用于保留工作参数中的数据。
  • 工作参数ITaskParam:负责工作门路记录以及工作产生的参数治理。
  • 工作执行后果ITaskResult:寄存工作最终执行的后果以及产生的数据。
  • 工作组IGroupTaskStep:负责兼顾调度各子工作步骤。

点击查看框架 UML 设计图

日志一览


集成指南

增加 Gradle 依赖

1. 先在我的项目根目录的 build.gradlerepositories 增加:

allprojects {
     repositories {
        ...
        maven {url "https://jitpack.io"}
    }
}

2. 而后在 dependencies 增加:

dependencies {
  ...
  // XTask
  implementation 'com.github.xuexiangjys:XTask:xtask-core:1.0.0'
}

应用办法

XTask 作为对外对立的 API 入口,所有罕用的办法都能从中找到。

关上调试模式

当须要定位问题,须要进行调试时,可关上调试模式,这样便可开启框架的日志。

XTask.debug(true);

XTask 的 API 介绍

办法名 形容
debug 设置是否关上调试
setLogger 自定义日志打印
setIsLogTaskRunThreadName 设置是否打印工作执行所在的线程名,默认 false
getTaskChain 获取工作链执行引擎
getTask 获取简化的工作
getTaskBuilder 获取简化工作的构建者
getConcurrentGroupTask 获取并行任务组
getSerialGroupTask 获取串行工作组
cancelTaskChain 勾销指定工作链执行
postToMain 执行工作到主线程
submit 执行一般异步工作
emergentSubmit 执行紧急异步工作
backgroundSubmit 执行后盾异步工作
ioSubmit 执行 io 耗时的异步工作
groupSubmit 执行分组异步工作

如何执行一条工作链

上面是一整个残缺的例子:

// 1. 创立一条工作链(必须)final TaskChainEngine engine = XTask.getTaskChain();
// 2. 设置工作链的初始化参数(可选)engine.setTaskParam(TaskParam.get("chainName", engine.getName()));
TaskParam taskParam = TaskParam.get("param1", 100)
        .put("param2", true);
// 3. 创立多个工作,并向工作链中增加(必须)XTaskStep taskStep = XTask.getTask(new TaskCommand() {
    @Override
    public void run() {ITaskParam param = getTaskParam();
        Log.e(TAG, getName() + "start, param1:" + param.get("param1") + ", chainName:" + param.get("chainName"));
        param.put("param1", 200);
        param.put("param3", "this is param3!");
    }
}, taskParam);
engine.addTask(taskStep)
        .addTask(XTask.getTask(new TaskCommand() {
            @Override
            public void run() {ITaskParam param = getTaskParam();
                Log.e(TAG, getName() + "start, param1:" + param.get("param1") + ", param3:" + param.get("param3"));
                param.put("param2", false);
            }
        }));
// 4. 设置工作链执行回调(可选)ICanceller canceller = engine.setTaskChainCallback(new TaskChainCallbackAdapter() {
    @Override
    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {Log.e(TAG, "task chain completed, thread:" + Thread.currentThread().getName());
        Map<String, Object> data = result.getDataStore().getData();
        for (Map.Entry<String, Object> entry : data.entrySet()) {Log.e(TAG, "key:" + entry.getKey() + ", value:" + entry.getValue());
        }
    }
// 5. 工作链执行(必须)}).start();

1. 创立一条工作链.(必须)

TaskChainEngine engine = XTask.getTaskChain();

2. 设置工作链的初始化参数.(可选)

engine.setTaskParam(TaskParam.get("chainName", engine.getName()));

3. 创立多个工作,并向工作链中增加.(必须)

// 设置工作初始化参数
TaskParam taskParam = TaskParam.get("param1", 100)
        .put("param2", true);
XTaskStep taskStep = XTask.getTask(new TaskCommand() {
    @Override
    public void run() {// ... 执行工作}
}, taskParam);
engine.addTask(taskStep)
        .addTask(XTask.getTask(new TaskCommand() {
            @Override
            public void run() {// ... 执行工作}
        }));

【留神】对于工作执行实现,须要留神以下两点:

  • 如果工作执行胜利,就调用 notifyTaskSucceed,工作执行失败,就调用notifyTaskFailed。这里工作无论胜利还是失败,只有执行实现都须要调用notifyTaskXXX 告诉工作链该工作实现,否则工作将无奈失常执行。
  • TaskCommandSimpleTaskStep 默认提供了主动告诉执行后果的性能,然而 AbstractTaskStep 没有提供,须要手动告诉。

4. 设置工作链执行回调.(可选)

调用 setTaskChainCallback 设置工作链执行回调。

engine.setTaskChainCallback(new TaskChainCallbackAdapter() {

    @Override
    public boolean isCallBackOnMainThread() {
        // 回调是否返回主线程, 默认是 true
        return false;
    }
    @Override
    public void onTaskChainStart(@NonNull ITaskChainEngine engine) {Log.e(TAG, "task chain start");
    }
    @Override
    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {Log.e(TAG, "task chain completed, thread:" + Thread.currentThread().getName());
    }
    @Override
    public void onTaskChainError(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {Log.e(TAG, "task chain error");
    }
})

5. 工作链执行.(必须)

调用 start 执行工作链。

ICanceller canceller = engine.start();

工作创立

创立工作有两种形式:

  • 通过 XTask.getTask 构建
  • 继承 SimpleTaskStep/AbstractTaskStep 实现工作的自定义

通过 XTask 创立

通过 XTask.getTask, 传入对应的属性进行构建

属性名 形容
name 工作步骤名称
command 工作执行内容
threadType 线程执行类型
taskParam 工作参数
taskHandler 工作解决者
isAutoNotify 是否主动告诉工作执行后果
XTaskStep taskStep = XTask.getTask(new TaskCommand() {
    @Override
    public void run() {// todo}
}, ThreadType.ASYNC, taskParam);

通过继承创立

通过继承 SimpleTaskStep 或者 AbstractTaskStep 实现具体性能。

public class StepATask extends SimpleTaskStep {

    @Override
    public void doTask() throws Exception {
        // todo
        // 不须要手动告诉工作链工作实现
    }
}

public class StepBTask extends AbstractTaskStep {

    @Override
    public void doTask() throws Exception {
        // todo
        // 需手动告诉工作链工作实现
        notifyTaskSucceed(TaskResult.succeed());
    }

    @Override
    public String getName() {return "StepATask";}
}

工作执行准则

每一个工作都是依靠于工作链进行流程管制。任何工作都须要遵循以下准则:

  • 任何工作无论失败还是胜利,都须要调用 notifyTaskSucceed 或者 notifyTaskFailed 去告诉工作链工作的实现状况。TaskCommandSimpleTaskStep 默认提供了主动告诉执行后果的性能。
  • 一旦工作链中某个工作执行失败,整个链路都进行工作。
工作类型 工作执行阐明
TaskCommand 主动告诉执行后果。如需手动告诉,只需设置 isAutoNotify 为 false 即可
SimpleTaskStep 主动告诉执行后果。如需手动告诉,只需重写 isAutoNotify 办法为 false 即可
AbstractTaskStep 需手动告诉执行后果

TaskCommand 手动告诉执行后果

在通过 XTask.getTask 传入 TaskCommand 构建 Task 的时候,设置 isAutoNotify 为 false 即可手动告诉执行后果。

final TaskChainEngine engine = XTask.getTaskChain();
for (int i = 0; i < 5; i++) {
    int finalI = i;
    engine.addTask(XTask.getTask(new TaskCommand() {
        @Override
        public void run() {
            try {Thread.sleep(1000);
            } catch (InterruptedException e) {e.printStackTrace();
            }
            if (finalI == 2) {notifyTaskFailed(404, "工作执行失败!");
            } else {notifyTaskSucceed(TaskResult.succeed());
            }
        }
    }, false)); // 设置手动告诉执行后果
}
engine.start();

SimpleTaskStep 手动告诉执行后果

重写 SimpleTaskStepisAutoNotify办法为 false 即可手动告诉执行后果。

public class StepATask extends SimpleTaskStep {

    @Override
    public void doTask() throws Exception {
        // todo
        // 手动告诉工作链工作实现
        notifyTaskSucceed();}

    @Override
    protected boolean isAutoNotify() {return false;}
}

参数传递

  • 任何 TaskStep 咱们都能够通过 getTaskParam 获取工作参数和工作执行后果ITaskParam
  • 上一个 TaskStep 保留解决过的工作参数会主动带入到下一个 TaskStep 中去,因而最初一个 TaskStep 领有之前所有工作的参数数据。
XTask.getTask(new TaskCommand() {
    @Override
    public void run() {ITaskParam param = getTaskParam();
        Log.e(TAG, getName() + "start, param1:" + param.get("param1") + ", param3:" + param.get("param3"));
        param.put("param2", false);
    }
})

线程管制

设置工作的 threadType 类型,即可实现对工作运行线程的管制。目前反对 6 种线程解决形式。

类型 形容 线程池形成
MAIN 主线程(UI 线程) /
ASYNC 异步线程(开子线程,一般线程池) 外围线程数和最大线程为 CPU 数,0s keepTime,LinkedBlockingQueue(128),线程优先级 5
ASYNC_IO 异步线程(开子线程,io 线程池) 外围线程数和最大线程为(2*CPU 数 +1),30s keepTime,LinkedBlockingQueue(128),线程优先级 5
ASYNC_EMERGENT 异步线程(开子线程,紧急线程池) 外围线程数为 2,最大线程为∞,60s keepTime,SynchronousQueue(不阻塞),线程优先级 10
ASYNC_BACKGROUND 异步线程(开子线程,优先级较低线程池) 外围线程数和最大线程为 2,0s keepTime,LinkedBlockingQueue(128),线程优先级 1
SYNC 同步线程(间接执行) /
// 1. 结构时传入线程
XTaskStep taskStep = XTask.getTask(new SimpleTaskCommand(1000), ThreadType.ASYNC_EMERGENT);
// 2. 设置线程的办法
taskStep.setThreadType(ThreadType.ASYNC_IO);

工作组

目前共有串行工作组(SerialGroupTaskStep)和并行任务组(ConcurrentGroupTaskStep)

串行工作组

串行工作组是按程序顺次执行,和工作链的解决形式相似。应用 XTask.getSerialGroupTask 获取。

final TaskChainEngine engine = XTask.getTaskChain();
SerialGroupTaskStep group1 = XTask.getSerialGroupTask("group1");
for (int i = 0; i < 5; i++) {group1.addTask(XTask.getTask(new SimpleTaskCommand(500)));
}
SerialGroupTaskStep group2 = XTask.getSerialGroupTask("group2");
for (int i = 0; i < 5; i++) {group2.addTask(XTask.getTask(new SimpleTaskCommand(1000)));
}
ICanceller canceller = engine.addTask(group1)
        .addTask(group2)
        .setTaskChainCallback(new TaskChainCallbackAdapter() {
            @Override
            public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {Log.e(TAG, "task chain completed, path:" + result.getPath());
            }
        })
        .start();
addCanceller(canceller);

并行任务组

并行任务组是组内所有工作同时执行,待所有工作都实现后才视为工作组实现。应用 XTask.getConcurrentGroupTask 获取。

final TaskChainEngine engine = XTask.getTaskChain();
ConcurrentGroupTaskStep group1 = XTask.getConcurrentGroupTask("group1");
for (int i = 0; i < 5; i++) {group1.addTask(XTask.getTask(new SimpleTaskCommand(100 * (i + 1))));
}
ConcurrentGroupTaskStep group2 = XTask.getConcurrentGroupTask("group2");
for (int i = 0; i < 5; i++) {group2.addTask(XTask.getTask(new SimpleTaskCommand(200 * (i + 1))));
}
ICanceller canceller = engine.addTask(group1)
        .addTask(group2)
        .setTaskChainCallback(new TaskChainCallbackAdapter() {
            @Override
            public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {Log.e(TAG, "task chain completed, path:" + result.getPath());
            }
        })
        .start();
addCanceller(canceller);

最初

如果你感觉这个我的项目对你有所帮忙, 你能够点击 star 进行珍藏或者将其分享进来, 让更多的人晓得这个我的项目!

我是 xuexiangjys,一枚酷爱学习,喜好编程,致力于 Android 架构钻研以及开源我的项目教训分享的技术 up 主。获取更多资讯,欢送微信搜寻公众号:【我的 Android 开源之旅】

正文完
 0