背景

很早之前接触了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开源之旅】