Full Code of xuexiangjys/XTask for AI

master ed9c0e79ca6e cached
173 files
698.9 KB
211.9k tokens
1086 symbols
1 requests
Download .txt
Showing preview only (792K chars total). Download the full file or copy to clipboard to get everything.
Repository: xuexiangjys/XTask
Branch: master
Commit: ed9c0e79ca6e
Files: 173
Total size: 698.9 KB

Directory structure:
gitextract_r5lsl1_p/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .idea/
│   └── copyright/
│       ├── profiles_settings.xml
│       └── xuexiang.xml
├── JitPackUpload.gradle
├── LICENSE
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── channel
│   ├── debug.jks
│   ├── multiple-channel.gradle
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── java/
│   │   │       └── com/
│   │   │           └── xuexiang/
│   │   │               └── xtaskdemo/
│   │   │                   └── ExampleInstrumentedTest.java
│   │   ├── main/
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── xuexiang/
│   │   │   │           └── xtaskdemo/
│   │   │   │               ├── MyApp.java
│   │   │   │               ├── activity/
│   │   │   │               │   └── MainActivity.java
│   │   │   │               ├── core/
│   │   │   │               │   ├── BaseActivity.java
│   │   │   │               │   ├── BaseContainerFragment.java
│   │   │   │               │   ├── BaseFragment.java
│   │   │   │               │   ├── BaseSimpleListFragment.java
│   │   │   │               │   └── SimpleListAdapter.java
│   │   │   │               ├── fragment/
│   │   │   │               │   ├── CustomTaskFragment.java
│   │   │   │               │   ├── MainFragment.java
│   │   │   │               │   ├── TestThreadPoolFragment.java
│   │   │   │               │   ├── UseCaseFragment.java
│   │   │   │               │   ├── XTaskStepFragment.java
│   │   │   │               │   ├── XTaskThreadFragment.java
│   │   │   │               │   ├── task/
│   │   │   │               │   │   ├── Job.java
│   │   │   │               │   │   ├── JobTask.java
│   │   │   │               │   │   ├── StepATask.java
│   │   │   │               │   │   └── StepBTask.java
│   │   │   │               │   └── usecase/
│   │   │   │               │       ├── AppStartFragment.java
│   │   │   │               │       ├── ComplexBusinessFragment.java
│   │   │   │               │       ├── ConcurrentProcessFragment.java
│   │   │   │               │       ├── appstart/
│   │   │   │               │       │   ├── job/
│   │   │   │               │       │   │   ├── AbstractMockJob.java
│   │   │   │               │       │   │   ├── LongTimeJob.java
│   │   │   │               │       │   │   ├── SingleJob.java
│   │   │   │               │       │   │   └── TopPriorityJob.java
│   │   │   │               │       │   └── task/
│   │   │   │               │       │       ├── AsyncInitTask.java
│   │   │   │               │       │       └── MainInitTask.java
│   │   │   │               │       ├── business/
│   │   │   │               │       │   ├── entity/
│   │   │   │               │       │   │   ├── Product.java
│   │   │   │               │       │   │   ├── ProductFactory.java
│   │   │   │               │       │   │   └── ProductInfo.java
│   │   │   │               │       │   ├── processor/
│   │   │   │               │       │   │   ├── AbstractProcessor.java
│   │   │   │               │       │   │   ├── GetProductInfoProcessor.java
│   │   │   │               │       │   │   ├── GivePriceProcessor.java
│   │   │   │               │       │   │   ├── PublicProductProcessor.java
│   │   │   │               │       │   │   └── SearchFactoryProcessor.java
│   │   │   │               │       │   └── task/
│   │   │   │               │       │       ├── AbstractTask.java
│   │   │   │               │       │       ├── GetProductInfoTask.java
│   │   │   │               │       │       ├── GivePriceTask.java
│   │   │   │               │       │       ├── ProductTaskConstants.java
│   │   │   │               │       │       ├── PublicProductTask.java
│   │   │   │               │       │       └── SearchFactoryTask.java
│   │   │   │               │       └── concurrent/
│   │   │   │               │           ├── entity/
│   │   │   │               │           │   ├── BriefInfo.java
│   │   │   │               │           │   ├── FactoryInfo.java
│   │   │   │               │           │   ├── PriceInfo.java
│   │   │   │               │           │   ├── Product.java
│   │   │   │               │           │   ├── PromotionInfo.java
│   │   │   │               │           │   └── RichInfo.java
│   │   │   │               │           ├── processor/
│   │   │   │               │           │   ├── GetBriefInfoProcessor.java
│   │   │   │               │           │   ├── GetFactoryInfoProcessor.java
│   │   │   │               │           │   ├── GetPriceInfoProcessor.java
│   │   │   │               │           │   ├── GetPromotionInfoProcessor.java
│   │   │   │               │           │   └── GetRichInfoProcessor.java
│   │   │   │               │           └── task/
│   │   │   │               │               ├── GetBriefInfoTask.java
│   │   │   │               │               ├── GetFactoryInfoTask.java
│   │   │   │               │               ├── GetPriceInfoTask.java
│   │   │   │               │               ├── GetPromotionInfoTask.java
│   │   │   │               │               └── GetRichInfoTask.java
│   │   │   │               └── utils/
│   │   │   │                   ├── XToastUtils.java
│   │   │   │                   ├── sdkinit/
│   │   │   │                   │   ├── UMengInit.java
│   │   │   │                   │   └── XBasicLibInit.java
│   │   │   │                   └── service/
│   │   │   │                       └── JsonSerializationService.java
│   │   │   └── res/
│   │   │       ├── drawable/
│   │   │       │   └── ic_launcher_background.xml
│   │   │       ├── drawable-v24/
│   │   │       │   └── ic_launcher_foreground.xml
│   │   │       ├── layout/
│   │   │       │   ├── adapter_item_simple_list_2.xml
│   │   │       │   ├── fragment_usecase_compare.xml
│   │   │       │   └── fragment_usecase_template.xml
│   │   │       ├── mipmap-anydpi-v26/
│   │   │       │   ├── ic_launcher.xml
│   │   │       │   └── ic_launcher_round.xml
│   │   │       └── values/
│   │   │           ├── colors.xml
│   │   │           ├── strings.xml
│   │   │           ├── styles.xml
│   │   │           └── styles_widget.xml
│   │   └── test/
│   │       └── java/
│   │           └── com/
│   │               └── xuexiang/
│   │                   └── xtaskdemo/
│   │                       └── ExampleUnitTest.java
│   └── x-library-simple.gradle
├── art/
│   └── xtask.mdj
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── versions.gradle
├── xtask-core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── xuexiang/
│                       └── xtask/
│                           ├── XTask.java
│                           ├── api/
│                           │   ├── TaskChainEngine.java
│                           │   └── step/
│                           │       ├── ConcurrentGroupTaskStep.java
│                           │       ├── SerialGroupTaskStep.java
│                           │       ├── SimpleTaskStep.java
│                           │       └── XTaskStep.java
│                           ├── core/
│                           │   ├── ITaskChainCallback.java
│                           │   ├── ITaskChainEngine.java
│                           │   ├── ThreadType.java
│                           │   ├── param/
│                           │   │   ├── IDataStore.java
│                           │   │   ├── ITaskParam.java
│                           │   │   ├── ITaskResult.java
│                           │   │   └── impl/
│                           │   │       ├── MapDataStore.java
│                           │   │       ├── TaskParam.java
│                           │   │       └── TaskResult.java
│                           │   └── step/
│                           │       ├── IGroupTaskStep.java
│                           │       ├── ITaskStep.java
│                           │       ├── ITaskStepController.java
│                           │       ├── ITaskStepHandler.java
│                           │       ├── ITaskStepLifecycle.java
│                           │       └── impl/
│                           │           ├── AbstractGroupTaskStep.java
│                           │           ├── AbstractTaskStep.java
│                           │           ├── AutoDestroyTaskChainCallback.java
│                           │           ├── AutoNotifyTaskStepHandler.java
│                           │           ├── TaskChainCallbackAdapter.java
│                           │           └── TaskCommand.java
│                           └── utils/
│                               ├── CancellerPoolUtils.java
│                               ├── CommonUtils.java
│                               └── TaskUtils.java
└── xtask-thread/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    └── src/
        └── main/
            ├── AndroidManifest.xml
            └── java/
                └── com/
                    └── xuexiang/
                        └── xtask/
                            ├── logger/
                            │   ├── ILogger.java
                            │   ├── LogcatLogger.java
                            │   └── TaskLogger.java
                            └── thread/
                                ├── XTaskExecutor.java
                                ├── executor/
                                │   ├── ICategoryExecutorCore.java
                                │   ├── IExecutorCore.java
                                │   ├── IPriorityExecutorCore.java
                                │   ├── IScheduledExecutorCore.java
                                │   └── impl/
                                │       ├── CategoryExecutorCore.java
                                │       ├── PriorityExecutorCore.java
                                │       └── ScheduledExecutorCore.java
                                ├── pool/
                                │   ├── DefaultScheduledThreadPoolExecutor.java
                                │   ├── DefaultThreadPoolExecutor.java
                                │   ├── PriorityThreadPoolExecutor.java
                                │   ├── TaskRecordPolicy.java
                                │   ├── TaskThreadFactory.java
                                │   ├── base/
                                │   │   ├── BaseScheduledThreadPoolExecutor.java
                                │   │   └── BaseThreadPoolExecutor.java
                                │   └── cancel/
                                │       ├── CancelHandlerRunnable.java
                                │       ├── ICancelable.java
                                │       ├── ICanceller.java
                                │       ├── ICancellerPool.java
                                │       ├── IFuture.java
                                │       ├── IScheduledFuture.java
                                │       └── TaskCancellerPool.java
                                ├── priority/
                                │   ├── IPriority.java
                                │   ├── IPriorityCallable.java
                                │   ├── IPriorityComparable.java
                                │   ├── IPriorityFuture.java
                                │   ├── IPriorityRunnable.java
                                │   ├── IPriorityStrategy.java
                                │   └── impl/
                                │       ├── DefaultPriorityCallable.java
                                │       ├── DefaultPriorityFuture.java
                                │       ├── DefaultPriorityRunnable.java
                                │       ├── DefaultPriorityStrategy.java
                                │       └── Priority.java
                                └── utils/
                                    ├── CancelUtils.java
                                    ├── ExecutorUtils.java
                                    └── PriorityUtils.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

custom: https://gitee.com/xuexiangjys/Resource/blob/master/doc/sponsor.md


================================================
FILE: .gitignore
================================================
*.iml
.gradle
/LocalRepository
/keystores
/local.properties
/.idea/caches
/.idea/codeStyles
/.idea/inspectionProfiles
/.idea/libraries
/.idea/dictionaries
/.idea/markdown-navigator
/.idea/*.xml
.DS_Store
/build
/captures
.externalNativeBuild

================================================
FILE: .idea/copyright/profiles_settings.xml
================================================
<component name="CopyrightManager">
  <settings default="xuexiang">
    <module2copyright>
      <element module="Project Files" copyright="xuexiang" />
    </module2copyright>
  </settings>
</component>

================================================
FILE: .idea/copyright/xuexiang.xml
================================================
<component name="CopyrightManager">
  <copyright>
    <option name="notice" value="Copyright (C) &amp;#36;today.year xuexiangjys(xuexiangjys@163.com)&#10;  &#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;      http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License.&#10;" />
    <option name="myName" value="xuexiang" />
  </copyright>
</component>

================================================
FILE: JitPackUpload.gradle
================================================
apply plugin: 'com.github.dcendents.android-maven'

// 指定group,com.github.<用户名>,这里我默认填写的是我的github账号,请换成你自己的。
group='com.github.xuexiangjys'

//---------------------------------------------


// 指定编码
tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

tasks.withType(Javadoc) {
    options.encoding = 'UTF-8'
}

if (project.hasProperty("android")) { // Android libraries
    task sourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }

    task javadoc(type: Javadoc) {
        failOnError  false
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }
} else { // Java libraries
    task sourcesJar(type: Jar, dependsOn: classes) {
        classifier = 'sources'
        from sourceSets.main.allSource
    }
}

javadoc {
    options {
        encoding "UTF-8"
        charSet 'UTF-8'
        author true
        version true
        links "http://docs.oracle.com/javase/7/docs/api"
    }
}

// 制作文档(Javadoc)
task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    archives javadocJar
    archives sourcesJar
}

================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.

"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.

2. Grant of Copyright License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.

4. Redistribution.

You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:

You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.

5. Submission of Contributions.

Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.

6. Trademarks.

This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.

7. Disclaimer of Warranty.

Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.

8. Limitation of Liability.

In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability.

While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work

To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.

   Copyright 2018 xuexiangjys

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: README.md
================================================
# XTask
[![](https://jitpack.io/v/xuexiangjys/XTask.svg)](https://jitpack.io/#xuexiangjys/XTask)
[![api](https://img.shields.io/badge/API-14+-brightgreen.svg)](https://android-arsenal.com/api?level=14)
[![I](https://img.shields.io/github/issues/xuexiangjys/XTask.svg)](https://github.com/xuexiangjys/XTask/issues)
[![Star](https://img.shields.io/github/stars/xuexiangjys/XTask.svg)](https://github.com/xuexiangjys/XTask)

一个拓展性极强的Android任务执行框架。可自由定义和组合任务来实现你想要的功能,尤其适用于处理复杂的业务流程,可灵活添加前置任务或者调整执行顺序。例如:应用的启动初始化流程。

在使用前,请一定要仔细阅读[使用说明文档](https://github.com/xuexiangjys/XTask/wiki),重要的事情说三遍!!!

在使用前,请一定要仔细阅读[使用说明文档](https://github.com/xuexiangjys/XTask/wiki),重要的事情说三遍!!!

在使用前,请一定要仔细阅读[使用说明文档](https://github.com/xuexiangjys/XTask/wiki),重要的事情说三遍!!!

## 关于我

| 公众号   | 掘金     |  知乎    |  CSDN   |   简书   |   思否  |   哔哩哔哩  |   今日头条
|---------|---------|--------- |---------|---------|---------|---------|---------|
| [我的Android开源之旅](https://t.1yb.co/Irse)  |  [点我](https://juejin.im/user/598feef55188257d592e56ed/posts)    |   [点我](https://www.zhihu.com/people/xuexiangjys/posts)       |   [点我](https://xuexiangjys.blog.csdn.net/)  |   [点我](https://www.jianshu.com/u/6bf605575337)  |   [点我](https://segmentfault.com/u/xuexiangjys)  |   [点我](https://space.bilibili.com/483850585)  |   [点我](https://img.rruu.net/image/5ff34ff7b02dd)

## X系列库快速集成

为了方便大家快速集成X系列框架库,我提供了一个空壳模版供大家参考使用: https://github.com/xuexiangjys/TemplateAppProject

除此之外,我还特别制作了几期[X系列视频教程](https://space.bilibili.com/483850585/channel/detail?cid=104998)供大家学习参考.

---

## 特征

* 支持6种线程类型方式执行任务。
* 支持任务链中各任务的执行线程调度和控制。
* 支持快捷任务创建,同时支持自定义任务。
* 支持串行和并行等组任务。
* 支持任务间数据共享。
* 支持自由组合任务执行。
* 支持任务链执行取消。
* 支持取消所有任务链和指定名称的任务链。
* 支持任务链调用顺序记录和查询。
* 支持自定义任务执行的线程池。

## 组成结构

* 任务链`ITaskChainEngine`:任务链执行引擎,负责统筹调度各任务步骤。

* 任务步骤`ITaskStep`:负责具体任务逻辑处理。

* 数据存储仓库`IDataStore`:存放数据的仓库,主要用于保存任务参数中的数据。

* 任务参数`ITaskParam`:负责任务路径记录以及任务产生的参数管理。

* 任务执行结果`ITaskResult`:存放任务最终执行的结果以及产生的数据。

* 任务组`IGroupTaskStep`:负责统筹调度各子任务步骤。

[点击查看框架UML设计图](https://github.com/xuexiangjys/XTask/blob/master/art/xtask_uml.png)

## 日志一览

![task_log.png](https://s4.ax1x.com/2022/02/16/HWdTHJ.png)

![task_log2.png](https://s4.ax1x.com/2022/02/16/HWwnbQ.png)

---

## 集成指南

### 添加Gradle依赖

1.先在项目根目录的 `build.gradle` 的 `repositories` 添加:

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

2.然后在应用项目(一般是app)的 `build.gradle` 的 dependencies 添加:

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

## 使用方法

> [XTask](https://github.com/xuexiangjys/XTask/blob/master/xtask-core/src/main/java/com/xuexiang/xtask/XTask.java)作为对外统一的API入口,所有常用的方法都能从中找到。

### 打开调试模式

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

```
XTask.debug(true);
```

### XTask的API介绍

方法名	| 描述
|---|---
debug | 设置是否打开调试
setLogger | 自定义日志打印
setIsLogThreadName | 设置是否打印任务执行所在的线程名,默认false
getTaskChain | 获取任务链执行引擎
getTask | 获取简化的任务
getTaskBuilder | 获取简化任务的构建者
getConcurrentGroupTask | 获取并行任务组
getSerialGroupTask | 获取串行任务组
cancelTaskChain | 取消指定任务链执行
cancelAllTaskChain | 取消所有任务链执行
postToMain | 执行任务到主线程
postToMainDelay | 延迟执行任务到主线程
submit | 执行普通异步任务
emergentSubmit | 执行紧急异步任务
backgroundSubmit | 执行后台异步任务
ioSubmit | 执行io耗时的异步任务
groupSubmit | 执行分组异步任务
schedule | 执行延期任务
scheduleAtFixedRate | 执行周期任务(固定间期)
scheduleWithFixedDelay | 执行周期任务(固定延期)

### 如何执行一条任务链

下面是一整个完整的例子:

```
// 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`通知任务链该任务完成,否则任务将无法正常执行。
* `TaskCommand`和`SimpleTaskStep`默认提供了自动通知执行结果的功能,但是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 | 任务步骤名称 | XTaskStep-N(N为自增数)
command | 任务执行内容 | /
threadType | 线程执行类型  | ThreadType.ASYNC
taskParam | 任务参数 | new TaskParam()
taskHandler | 任务处理者 | null
isAutoNotify | 是否自动通知任务执行结果 | true
```
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`去通知任务链任务的完成情况。`TaskCommand`和`SimpleTaskStep`默认提供了自动通知执行结果的功能。
* 一旦任务链中某个任务执行失败,整个链路都停止工作。

任务类型	| 任务执行说明
|---|---
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手动通知执行结果

重写`SimpleTaskStep`的`isAutoNotify`方法为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);
```

## 任务链取消

> 通过调用`ICanceller`的`cancel`方法或者`XTask`的`cancelTaskChain`即可完成任务链的取消。

### 单个任务链取消

调用任务链`TaskChainEngine`的`start`方法之后,会返回一个任务取消者`ICanceller`,调用它的`cancel`方法即可完成任务取消。

```
ICanceller canceller = engine.start();
// 取消任务链的执行
canceller.cancel();
```

### 多个任务链取消

任务链在执行的时候,会默认加入到一个任务取消池,调用`XTask`的`cancelTaskChain`方法,传入多个任务链的名称或者`ICanceller`的名称,即可完成多个任务链的取消。

```
Set<String> pool = new HashSet<>();
ICanceller canceller1 = engine1.start();
ICanceller canceller2 = engine2.start();
// 使用ICanceller的名称
pool.add(canceller1.getName());
// 使用任务链的名称
pool.add(engine2.getName());
// 取消多个任务链的执行
XTask.cancelTaskChain(pool);
```

### 全部任务链取消

调用`XTask`的`cancelAllTaskChain`方法取消全部任务链的执行

```
XTask.cancelAllTaskChain();
```

---

## 如果觉得项目还不错,可以考虑打赏一波

> 你的打赏是我维护的动力,我将会列出所有打赏人员的清单在下方作为凭证,打赏前请留下打赏项目的备注!

![pay.png](https://raw.githubusercontent.com/xuexiangjys/Resource/master/img/pay/pay.png)

## 联系方式

> 更多资讯内容,欢迎扫描关注我的个人微信公众号:【我的Android开源之旅】

![](https://s1.ax1x.com/2022/04/27/LbGMJH.jpg)


================================================
FILE: app/.gitignore
================================================
/build


================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'img-optimizer'
//打包时,记得设置true启用
if (isNeedPackage.toBoolean() && isUseBooster.toBoolean()) {
    apply plugin: 'com.didiglobal.booster'
}

android {
    compileSdkVersion build_versions.target_sdk
    buildToolsVersion build_versions.build_tools

    defaultConfig {
        applicationId "com.xuexiang.xtaskdemo"
        minSdkVersion 17
        targetSdkVersion build_versions.target_sdk
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        multiDexEnabled true
        vectorDrawables.useSupportLibrary = true

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
    }

    signingConfigs {
        if (isNeedPackage.toBoolean()) {
            release {
                storeFile file(app_release.storeFile)
                storePassword app_release.storePassword
                keyAlias app_release.keyAlias
                keyPassword app_release.keyPassword
            }
        }

        debug {
            storeFile file("./debug.jks")
            storePassword "123456"
            keyAlias "debug"
            keyPassword "123456"
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            if (isNeedPackage.toBoolean()) {
                signingConfig signingConfigs.release

                Properties properties = new Properties()
                properties.load(project.rootProject.file('local.properties').newDataInputStream())
                def appID = properties.getProperty("APP_ID_UMENG")
                if (appID != null) {
                    buildConfigField "String", "APP_ID_UMENG", appID
                } else {
                    buildConfigField "String", "APP_ID_UMENG", '""'
                }
            } else {
                signingConfig signingConfigs.debug
                buildConfigField "String", "APP_ID_UMENG", '""'
            }
        }

        debug {
            debuggable true
            minifyEnabled false

            signingConfig signingConfigs.debug
            buildConfigField "String", "APP_ID_UMENG", '""'
        }
    }

    lintOptions {
        abortOnError false
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation deps.junit
    androidTestImplementation deps.runner
    androidTestImplementation deps.espresso.core

    // 任务库
    implementation project(':xtask-core')
//    implementation 'com.github.xuexiangjys.XTask:xtask-core:1.0.2'

    // rxjava3
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    implementation 'io.reactivex.rxjava3:rxjava:3.1.3'
    implementation deps.androidx.multidex
    // 屏幕适配AutoSize
    implementation 'me.jessyan:autosize:1.2.1'
    // umeng统计
    implementation 'com.umeng.umsdk:common:9.3.8'
    implementation 'com.umeng.umsdk:asms:1.2.1'

    // 美团多渠道打包
    implementation 'com.meituan.android.walle:library:1.1.6'
}

// x-library依赖脚本
apply from: 'x-library-simple.gradle'
// walle多渠道打包
apply from: 'multiple-channel.gradle'



================================================
FILE: app/channel
================================================
# 美团
meituan
# 三星
samsungapps
# 小米
xiaomi
# 91助手
91com
# 魅族
meizu
# 豌豆荚
wandou
# Google Play
googleplay
# 百度
baidu
# 360
360cn
# 应用宝
myapp
# 华为
huawei
# 蒲公英
pgyer
github

================================================
FILE: app/multiple-channel.gradle
================================================
apply plugin: 'walle'

walle {
    // 指定渠道包的输出路径
    apkOutputFolder = new File("${project.buildDir}/outputs/channels")
    // 定制渠道包的APK的文件名称
    apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'
    // 渠道配置文件
    channelFile = new File("${project.getProjectDir()}/channel")
}

================================================
FILE: app/proguard-rules.pro
================================================
#=========================================基础不变的混淆配置=========================================##
#指定代码的压缩级别
-optimizationpasses 5
#包名不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共的库的类的成员
-dontskipnonpubliclibraryclassmembers
#优化  不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*
#忽略警告
-ignorewarnings

##记录生成的日志数据,gradle build时在本项目根目录输出##
#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt
# 并保留源文件名为"Proguard"字符串,而非原始的类名 并保留行号
-keepattributes SourceFile,LineNumberTable
########记录生成的日志数据,gradle build时 在本项目根目录输出-end#####

#需要保留的东西
# 保持哪些类不被混淆
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.support.v4.**
-keep public class com.android.vending.licensing.ILicensingService

#如果有引用v4包可以添加下面这行
-keep public class * extends android.support.v4.app.Fragment

##########JS接口类不混淆,否则执行不了
-dontwarn com.android.JsInterface.**
-keep class com.android.JsInterface.** {*; }

#极光推送和百度lbs android sdk一起使用proguard 混淆的问题#http的类被混淆后,导致apk定位失败,保持apache 的http类不被混淆就好了
-dontwarn org.apache.**
-keep class org.apache.**{ *; }

-keep public class * extends android.view.View {
  public <init>(android.content.Context);
  public <init>(android.content.Context, android.util.AttributeSet);
  public <init>(android.content.Context, android.util.AttributeSet, int);
  public void set*(...);
 }

#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
  native <methods>;
}

#保持自定义控件类不被混淆
-keepclasseswithmembers class * {
  public <init>(android.content.Context, android.util.AttributeSet);
}

#保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
  public void *(android.view.View);
}

#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable

#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

#保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
-keepclassmembers enum * {
      public static **[] values();
      public static ** valueOf(java.lang.String);
}

-keepclassmembers class * {
      public void *ButtonClicked(android.view.View);
}

#不混淆资源类
-keep class **.R$* {*;}

#===================================混淆保护自己项目的部分代码以及引用的第三方jar包library=============================#######
#如果引用了v4或者v7包
-dontwarn android.support.**


# AndroidX 防止混淆
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**
-keep class com.google.android.material.** {*;}
-keep class androidx.** {*;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-keepclassmembers class * {
    @androidx.annotation.Keep *;
}

# zxing
-dontwarn com.google.zxing.**
-keep class com.google.zxing.**{*;}

#SignalR推送
-keep class microsoft.aspnet.signalr.** { *; }

# 极光推送混淆
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }

# 数据库框架OrmLite
-keepattributes *DatabaseField*
-keepattributes *DatabaseTable*
-keepattributes *SerializedName*
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; }

#XHttp2
-keep class com.xuexiang.xhttp2.model.** { *; }
-keep class com.xuexiang.xhttp2.cache.model.** { *; }
-keep class com.xuexiang.xhttp2.cache.stategy.**{*;}
-keep class com.xuexiang.xhttp2.annotation.** { *; }

#okhttp
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**
-dontwarn javax.annotation.Nullable
-dontwarn javax.annotation.ParametersAreNonnullByDefault
-dontwarn javax.annotation.**

#如果用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错
-keepattributes Signature
-keep class com.google.gson.stream.** { *; }
-keepattributes EnclosingMethod
-keep class org.xz_sale.entity.**{*;}
-keep class com.google.gson.** {*;}
-keep class com.google.**{*;}
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }

# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Exceptions

# RxJava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
    long producerIndex;
    long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

-dontwarn okio.**
-dontwarn javax.annotation.Nullable
-dontwarn javax.annotation.ParametersAreNonnullByDefault
-dontwarn javax.annotation.**

# fastjson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }
-keepattributes Signature

# xpage
-keep class com.xuexiang.xpage.annotation.** { *; }
-keep class com.xuexiang.xpage.config.** { *; }

# xaop
-keep @com.xuexiang.xaop.annotation.* class * {*;}
-keep @org.aspectj.lang.annotation.* class * {*;}
-keep class * {
    @com.xuexiang.xaop.annotation.* <fields>;
    @org.aspectj.lang.annotation.* <fields>;
}
-keepclassmembers class * {
    @com.xuexiang.xaop.annotation.* <methods>;
    @org.aspectj.lang.annotation.* <methods>;
}

# xrouter
-keep public class com.xuexiang.xrouter.routes.**{*;}
-keep class * implements com.xuexiang.xrouter.facade.template.ISyringe{*;}
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
-keep class * implements com.xuexiang.xrouter.facade.template.IProvider

# xupdate
-keep class com.xuexiang.xupdate.entity.** { *; }

# xvideo
-keep class com.xuexiang.xvideo.jniinterface.** { *; }

# xipc
-keep @com.xuexiang.xipc.annotation.* class * {*;}
-keep class * {
    @com.xuexiang.xipc.annotation.* <fields>;
}
-keepclassmembers class * {
    @com.xuexiang.xipc.annotation.* <methods>;
}

# umeng统计
-keep class com.umeng.** {*;}
-keepclassmembers class * {
   public <init> (org.json.JSONObject);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# materialedittext
-keep class com.xuexiang.xui.widget.edittext.materialedittext.** { *; }


================================================
FILE: app/src/androidTest/java/com/xuexiang/xtaskdemo/ExampleInstrumentedTest.java
================================================
package com.xuexiang.xtaskdemo;

import android.content.Context;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();

        assertEquals("com.xuexiang.templateproject", appContext.getPackageName());
    }
}


================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.xuexiang.xtaskdemo">

    <!--进程杀死-->
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />

    <application
        android:name="com.xuexiang.xtaskdemo.MyApp"
        android:allowBackup="false"
        android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:windowSoftInputMode="adjustPan|stateHidden"
        tools:ignore="LockedOrientationActivity">

        <activity
            android:name="com.xuexiang.xtaskdemo.activity.MainActivity"
            android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustPan|stateHidden">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--fragment的页面容器-->
        <activity
            android:name="com.xuexiang.xtaskdemo.core.BaseActivity"
            android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustPan|stateHidden" />

        <!--屏幕自适应设计图-->
        <meta-data
            android:name="design_width_in_dp"
            android:value="360" />
        <meta-data
            android:name="design_height_in_dp"
            android:value="640" />

    </application>

</manifest>

================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/MyApp.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo;

import android.app.Application;
import android.content.Context;

import androidx.multidex.MultiDex;

import com.xuexiang.xtask.XTask;
import com.xuexiang.xtaskdemo.utils.sdkinit.UMengInit;
import com.xuexiang.xtaskdemo.utils.sdkinit.XBasicLibInit;

/**
 * @author xuexiang
 * @since 2018/11/7 下午1:12
 */
public class MyApp extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        //解决4.x运行崩溃的问题
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initLibs();

        // 设置XTask的调试模式
        XTask.debug(isDebug());
//        // 设置是否打印任务执行所在的线程名
//        XTask.setIsLogThreadName(true);
    }

    /**
     * 初始化基础库
     */
    private void initLibs() {
        XBasicLibInit.init(this);
        UMengInit.init(this);
    }


    /**
     * @return 当前app是否是调试开发模式
     */
    public static boolean isDebug() {
        return BuildConfig.DEBUG;
    }


}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/activity/MainActivity.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.activity;

import android.os.Bundle;

import com.xuexiang.xtaskdemo.core.BaseActivity;
import com.xuexiang.xtaskdemo.fragment.MainFragment;

/**
 * 程序入口,空壳容器
 *
 * @author xuexiang
 * @since 2019-07-07 23:53
 */
public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        openPage(MainFragment.class);
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseActivity.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.core;

import android.content.Context;
import android.os.Bundle;

import com.xuexiang.xpage.base.XPageActivity;
import com.xuexiang.xpage.base.XPageFragment;
import com.xuexiang.xpage.core.CoreSwitchBean;
import com.xuexiang.xrouter.facade.service.SerializationService;
import com.xuexiang.xrouter.launcher.XRouter;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.github.inflationx.viewpump.ViewPumpContextWrapper;

/**
 * 基础容器Activity
 *
 * @author XUE
 * @since 2019/3/22 11:21
 */
public class BaseActivity extends XPageActivity {

    Unbinder mUnbinder;

    @Override
    protected void attachBaseContext(Context newBase) {
        //注入字体
        super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        initStatusBarStyle();
        super.onCreate(savedInstanceState);
        mUnbinder = ButterKnife.bind(this);
    }

    /**
     * 初始化状态栏的样式
     */
    protected void initStatusBarStyle() {

    }

    /**
     * 打开fragment
     *
     * @param clazz          页面类
     * @param addToBackStack 是否添加到栈中
     * @return 打开的fragment对象
     */
    public <T extends XPageFragment> T openPage(Class<T> clazz, boolean addToBackStack) {
        CoreSwitchBean page = new CoreSwitchBean(clazz)
                .setAddToBackStack(addToBackStack);
        return (T) openPage(page);
    }

    /**
     * 打开fragment
     *
     * @return 打开的fragment对象
     */
    public <T extends XPageFragment> T openNewPage(Class<T> clazz) {
        CoreSwitchBean page = new CoreSwitchBean(clazz)
                .setNewActivity(true);
        return (T) openPage(page);
    }

    /**
     * 切换fragment
     *
     * @param clazz 页面类
     * @return 打开的fragment对象
     */
    public <T extends XPageFragment> T switchPage(Class<T> clazz) {
        return openPage(clazz, false);
    }

    /**
     * 序列化对象
     *
     * @param object
     * @return
     */
    public String serializeObject(Object object) {
        return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
    }

    @Override
    protected void onRelease() {
        mUnbinder.unbind();
        super.onRelease();
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseContainerFragment.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.core;

import android.content.res.Configuration;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;

import com.umeng.analytics.MobclickAgent;
import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.base.XPageContainerListFragment;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.actionbar.TitleUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.xuexiang.xtaskdemo.core.SimpleListAdapter.KEY_SUB_TITLE;
import static com.xuexiang.xtaskdemo.core.SimpleListAdapter.KEY_TITLE;

/**
 * 修改列表样式为主副标题显示
 *
 * @author xuexiang
 * @since 2018/11/22 上午11:26
 */
public abstract class BaseContainerFragment extends XPageContainerListFragment {

    @Override
    protected void initPage() {
        initTitle();
        initViews();
        initListeners();
    }

    protected TitleBar initTitle() {
        return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popToBack();
            }
        });
    }

    @Override
    protected void initData() {
        mSimpleData = initSimpleData(mSimpleData);

        List<Map<String, String>> data = new ArrayList<>();
        for (String content : mSimpleData) {
            Map<String, String> item = new HashMap<>();
            int index = content.indexOf("\n");
            if (index > 0) {
                item.put(KEY_TITLE, String.valueOf(content.subSequence(0, index)));
                item.put(KEY_SUB_TITLE, String.valueOf(content.subSequence(index + 1, content.length())));
            } else {
                item.put(KEY_TITLE, content);
                item.put(KEY_SUB_TITLE, "");
            }
            data.add(item);
        }

        getListView().setAdapter(new SimpleListAdapter(getContext(), data));
        initSimply();
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        onItemClick(view, position);
    }

    @SingleClick
    private void onItemClick(View view, int position) {
        onItemClick(position);
    }

    @Override
    public void onDestroyView() {
        getListView().setOnItemClickListener(null);
        super.onDestroyView();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        //屏幕旋转时刷新一下title
        super.onConfigurationChanged(newConfig);
        ViewGroup root = (ViewGroup) getRootView();
        if (root.getChildAt(0) instanceof TitleBar) {
            root.removeViewAt(0);
            initTitle();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        MobclickAgent.onPageStart(getPageName());
    }

    @Override
    public void onPause() {
        super.onPause();
        MobclickAgent.onPageEnd(getPageName());
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseFragment.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.core;

import android.content.res.Configuration;
import android.os.Parcelable;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.umeng.analytics.MobclickAgent;
import com.xuexiang.xpage.base.XPageActivity;
import com.xuexiang.xpage.base.XPageFragment;
import com.xuexiang.xpage.core.PageOption;
import com.xuexiang.xpage.enums.CoreAnim;
import com.xuexiang.xpage.utils.Utils;
import com.xuexiang.xrouter.facade.service.SerializationService;
import com.xuexiang.xrouter.launcher.XRouter;
import com.xuexiang.xui.utils.WidgetUtils;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.actionbar.TitleUtils;
import com.xuexiang.xui.widget.progress.loading.IMessageLoader;

import java.io.Serializable;
import java.lang.reflect.Type;

/**
 * 基础fragment
 *
 * @author xuexiang
 * @since 2018/5/25 下午3:44
 */
public abstract class BaseFragment extends XPageFragment {

    private IMessageLoader mIMessageLoader;

    @Override
    protected void initPage() {
        initTitle();
        initViews();
        initListeners();
    }

    protected TitleBar initTitle() {
        return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), v -> popToBack());
    }

    @Override
    protected void initListeners() {

    }

    public IMessageLoader getMessageLoader() {
        if (mIMessageLoader == null) {
            mIMessageLoader = WidgetUtils.getMiniLoadingDialog(getContext());
        }
        return mIMessageLoader;
    }

    public IMessageLoader getMessageLoader(String message) {
        if (mIMessageLoader == null) {
            mIMessageLoader = WidgetUtils.getMiniLoadingDialog(getContext(), message);
        } else {
            mIMessageLoader.updateMessage(message);
        }
        return mIMessageLoader;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        //屏幕旋转时刷新一下title
        super.onConfigurationChanged(newConfig);
        ViewGroup root = (ViewGroup) getRootView();
        if (root.getChildAt(0) instanceof TitleBar) {
            root.removeViewAt(0);
            initTitle();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        MobclickAgent.onPageStart(getPageName());
    }

    @Override
    public void onPause() {
        super.onPause();
        MobclickAgent.onPageEnd(getPageName());
    }


    //==============================页面跳转api===================================//

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz 页面的类
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
        return new PageOption(clazz)
                .setNewActivity(true)
                .open(this);
    }

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param pageName 页面名
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(String pageName) {
        return new PageOption(pageName)
                .setAnim(CoreAnim.slide)
                .setNewActivity(true)
                .open(this);
    }


    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz                页面的类
     * @param containActivityClazz 页面容器
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
        return new PageOption(clazz)
                .setNewActivity(true)
                .setContainActivityClazz(containActivityClazz)
                .open(this);
    }

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
        PageOption option = new PageOption(clazz).setNewActivity(true);
        return openPage(option, key, value);
    }

    public Fragment openPage(PageOption option, String key, Object value) {
        if (value instanceof Integer) {
            option.putInt(key, (Integer) value);
        } else if (value instanceof Float) {
            option.putFloat(key, (Float) value);
        } else if (value instanceof String) {
            option.putString(key, (String) value);
        } else if (value instanceof Boolean) {
            option.putBoolean(key, (Boolean) value);
        } else if (value instanceof Long) {
            option.putLong(key, (Long) value);
        } else if (value instanceof Double) {
            option.putDouble(key, (Double) value);
        } else if (value instanceof Parcelable) {
            option.putParcelable(key, (Parcelable) value);
        } else if (value instanceof Serializable) {
            option.putSerializable(key, (Serializable) value);
        } else {
            option.putString(key, serializeObject(value));
        }
        return option.open(this);
    }

    /**
     * 打开页面
     *
     * @param clazz          页面的类
     * @param addToBackStack 是否加入回退栈
     * @param key            入参的键
     * @param value          入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
        return new PageOption(clazz)
                .setAddToBackStack(addToBackStack)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
        return openPage(clazz, true, key, value);
    }

    /**
     * 打开页面
     *
     * @param clazz          页面的类
     * @param addToBackStack 是否加入回退栈
     * @param key            入参的键
     * @param value          入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
        PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
        return openPage(option, key, value);
    }

    /**
     * 打开页面
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
        return new PageOption(clazz)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param key         入参的键
     * @param value       入参的值
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
        PageOption option = new PageOption(clazz).setRequestCode(requestCode);
        return openPage(option, key, value);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param key         入参的键
     * @param value       入参的值
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
        return new PageOption(clazz)
                .setRequestCode(requestCode)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
        return new PageOption(clazz)
                .setRequestCode(requestCode)
                .open(this);
    }

    /**
     * 序列化对象
     *
     * @param object 需要序列化的对象
     * @return 序列化结果
     */
    public String serializeObject(Object object) {
        return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
    }

    /**
     * 反序列化对象
     *
     * @param input 反序列化的内容
     * @param clazz 类型
     * @return 反序列化结果
     */
    public <T> T deserializeObject(String input, Type clazz) {
        return XRouter.getInstance().navigation(SerializationService.class).parseObject(input, clazz);
    }

    @Override
    protected void hideCurrentPageSoftInput() {
        if (getActivity() == null) {
            return;
        }
        // 记住,要在xml的父布局加上android:focusable="true" 和 android:focusableInTouchMode="true"
        Utils.hideSoftInputClearFocus(getActivity().getCurrentFocus());
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseSimpleListFragment.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.core;

import android.content.res.Configuration;
import android.os.Parcelable;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.umeng.analytics.MobclickAgent;
import com.xuexiang.xpage.base.XPageActivity;
import com.xuexiang.xpage.base.XPageFragment;
import com.xuexiang.xpage.base.XPageSimpleListFragment;
import com.xuexiang.xpage.core.PageOption;
import com.xuexiang.xpage.enums.CoreAnim;
import com.xuexiang.xrouter.facade.service.SerializationService;
import com.xuexiang.xrouter.launcher.XRouter;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.actionbar.TitleUtils;

import java.io.Serializable;

/**
 * @author xuexiang
 * @since 2018/12/29 下午12:41
 */
public abstract class BaseSimpleListFragment extends XPageSimpleListFragment {

    @Override
    protected void initPage() {
        initTitle();
        initViews();
        initListeners();
    }

    protected TitleBar initTitle() {
        return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popToBack();
            }
        });
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        //屏幕旋转时刷新一下title
        super.onConfigurationChanged(newConfig);
        ViewGroup root = (ViewGroup) getRootView();
        if (root.getChildAt(0) instanceof TitleBar) {
            root.removeViewAt(0);
            initTitle();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        MobclickAgent.onPageStart(getPageName());
    }

    @Override
    public void onPause() {
        super.onPause();
        MobclickAgent.onPageEnd(getPageName());
    }

    //==============================页面跳转api===================================//

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz 页面的类
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
        return new PageOption(clazz)
                .setNewActivity(true)
                .open(this);
    }

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param pageName 页面名
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(String pageName) {
        return new PageOption(pageName)
                .setAnim(CoreAnim.slide)
                .setNewActivity(true)
                .open(this);
    }


    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz                页面的类
     * @param containActivityClazz 页面容器
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
        return new PageOption(clazz)
                .setNewActivity(true)
                .setContainActivityClazz(containActivityClazz)
                .open(this);
    }

    /**
     * 打开一个新的页面【建议只在主tab页使用】
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
        PageOption option = new PageOption(clazz).setNewActivity(true);
        return openPage(option, key, value);
    }

    public Fragment openPage(PageOption option, String key, Object value) {
        if (value instanceof Integer) {
            option.putInt(key, (Integer) value);
        } else if (value instanceof Float) {
            option.putFloat(key, (Float) value);
        } else if (value instanceof String) {
            option.putString(key, (String) value);
        } else if (value instanceof Boolean) {
            option.putBoolean(key, (Boolean) value);
        } else if (value instanceof Long) {
            option.putLong(key, (Long) value);
        } else if (value instanceof Double) {
            option.putDouble(key, (Double) value);
        } else if (value instanceof Parcelable) {
            option.putParcelable(key, (Parcelable) value);
        } else if (value instanceof Serializable) {
            option.putSerializable(key, (Serializable) value);
        } else {
            option.putString(key, serializeObject(value));
        }
        return option.open(this);
    }

    /**
     * 打开页面
     *
     * @param clazz          页面的类
     * @param addToBackStack 是否加入回退栈
     * @param key            入参的键
     * @param value          入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
        return new PageOption(clazz)
                .setAddToBackStack(addToBackStack)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
        return openPage(clazz, true, key, value);
    }

    /**
     * 打开页面
     *
     * @param clazz          页面的类
     * @param addToBackStack 是否加入回退栈
     * @param key            入参的键
     * @param value          入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
        PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
        return openPage(option, key, value);
    }

    /**
     * 打开页面
     *
     * @param clazz 页面的类
     * @param key   入参的键
     * @param value 入参的值
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
        return new PageOption(clazz)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param key         入参的键
     * @param value       入参的值
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
        PageOption option = new PageOption(clazz).setRequestCode(requestCode);
        return openPage(option, key, value);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param key         入参的键
     * @param value       入参的值
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
        return new PageOption(clazz)
                .setRequestCode(requestCode)
                .putString(key, value)
                .open(this);
    }

    /**
     * 打开页面,需要结果返回
     *
     * @param clazz       页面的类
     * @param requestCode 请求码
     * @param <T>
     * @return
     */
    public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
        return new PageOption(clazz)
                .setRequestCode(requestCode)
                .open(this);
    }

    /**
     * 序列化对象
     *
     * @param object 需要序列化的对象
     * @return 序列化结果
     */
    public String serializeObject(Object object) {
        return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/SimpleListAdapter.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.core;

import android.content.Context;
import android.view.View;
import android.widget.TextView;

import com.xuexiang.xtaskdemo.R;
import com.xuexiang.xui.adapter.listview.BaseListAdapter;
import com.xuexiang.xutil.common.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * 主副标题显示适配器
 *
 * @author xuexiang
 * @since 2018/12/19 上午12:19
 */
public class SimpleListAdapter extends BaseListAdapter<Map<String, String>, SimpleListAdapter.ViewHolder> {

    public static final String KEY_TITLE = "title";
    public static final String KEY_SUB_TITLE = "sub_title";

    public SimpleListAdapter(Context context, List<Map<String, String>> data) {
        super(context, data);
    }

    @Override
    protected ViewHolder newViewHolder(View convertView) {
        ViewHolder holder = new ViewHolder();
        holder.mTvTitle = convertView.findViewById(R.id.tv_title);
        holder.mTvSubTitle = convertView.findViewById(R.id.tv_sub_title);
        return holder;
    }

    @Override
    protected int getLayoutId() {
        return R.layout.adapter_item_simple_list_2;
    }

    @Override
    protected void convert(ViewHolder holder, Map<String, String> item, int position) {
        holder.mTvTitle.setText(item.get(KEY_TITLE));
        if (!StringUtils.isEmpty(item.get(KEY_SUB_TITLE))) {
            holder.mTvSubTitle.setText(item.get(KEY_SUB_TITLE));
            holder.mTvSubTitle.setVisibility(View.VISIBLE);
        } else {
            holder.mTvSubTitle.setVisibility(View.GONE);
        }
    }

    public static class ViewHolder {
        /**
         * 标题
         */
        public TextView mTvTitle;
        /**
         * 副标题
         */
        public TextView mTvSubTitle;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/CustomTaskFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import android.util.Log;

import androidx.annotation.NonNull;

import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.api.TaskChainEngine;
import com.xuexiang.xtask.api.step.SimpleTaskStep;
import com.xuexiang.xtask.core.ITaskChainEngine;
import com.xuexiang.xtask.core.ThreadType;
import com.xuexiang.xtask.core.param.ITaskParam;
import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtask.core.param.impl.TaskParam;
import com.xuexiang.xtask.core.step.impl.TaskChainCallbackAdapter;
import com.xuexiang.xtask.thread.pool.cancel.ICanceller;
import com.xuexiang.xtaskdemo.core.BaseSimpleListFragment;
import com.xuexiang.xtaskdemo.fragment.task.Job;
import com.xuexiang.xtaskdemo.fragment.task.JobTask;
import com.xuexiang.xtaskdemo.fragment.task.StepATask;
import com.xuexiang.xtaskdemo.fragment.task.StepBTask;
import com.xuexiang.xutil.common.ObjectUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author xuexiang
 * @since 2/1/22 11:07 PM
 */
@Page(name = "自定义任务使用\n通过继承SimpleTaskStep/AbstractTaskStep实现")
public class CustomTaskFragment extends BaseSimpleListFragment {

    public static final String TAG = "CustomTaskFragment";

    private Set<String> mPool = new HashSet<>();

    @Override
    protected List<String> initSimpleData(List<String> lists) {
        lists.add("简单继承SimpleTaskStep使用");
        lists.add("简单继承AbstractTaskStep使用");
        lists.add("复杂任务使用");
        return lists;
    }

    @Override
    protected void onItemClick(int position) {
        switch (position) {
            case 0:
                doSimpleTaskStep();
                break;
            case 1:
                doSimpleAbstractTaskStep();
                break;
            case 2:
                doComplexTaskStep();
                break;
            default:
                break;
        }
    }

    /**
     * 简单继承SimpleTaskStep使用
     */
    private void doSimpleTaskStep() {
        final TaskChainEngine engine = XTask.getTaskChain();
        ICanceller canceller = engine
                .addTask(new SimpleTaskStep("TaskStep1", ThreadType.ASYNC_IO) {
                    @Override
                    public void doTask() throws Exception {
                        Log.e(CustomTaskFragment.TAG, "doing TaskStep1...., thread:" + Thread.currentThread().getName());
                        // 模拟耗时
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        getTaskParam().put(StepATask.KEY_TOTAL, 123);
                    }
                })
                .addTask(new SimpleTaskStep("TaskStep2", ThreadType.SYNC) {
                    @Override
                    public void doTask() throws Exception {
                        Log.e(CustomTaskFragment.TAG, "doing TaskStep2...., thread:" + Thread.currentThread().getName());
                        // 模拟耗时
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ITaskParam param = getTaskParam();
                        param.put(StepATask.KEY_TOTAL, param.getInt(StepATask.KEY_TOTAL) + 321);
                        notifyTaskSucceed();
                    }

                    @Override
                    protected boolean isAutoNotify() {
                        // 设置手动通知执行结果
                        return false;
                    }
                })
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        Log.e(TAG, "task chain completed, thread:" + Thread.currentThread().getName() + ", result:" + result.getDataStore().getInt(StepATask.KEY_TOTAL));
                    }
                })
                .start();
        addCanceller(canceller);
    }

    /**
     * 简单继承AbstractTaskStep使用
     */
    private void doSimpleAbstractTaskStep() {
        final TaskChainEngine engine = XTask.getTaskChain();
        ICanceller canceller = engine.addTask(new StepATask())
                .addTask(new StepBTask())
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        Log.e(TAG, "task chain completed, result:" + result.getDataStore().getInt(StepATask.KEY_TOTAL));
                    }
                })
                .start();
        addCanceller(canceller);
    }

    /**
     * 复杂任务使用
     */
    private void doComplexTaskStep() {
        final TaskChainEngine engine = XTask.getTaskChain();
        TaskParam taskParam = TaskParam.get(Job.KEY_JOB_TARGET, 100);
        engine.setTaskParam(taskParam);
        for (int i = 0; i < 5; i++) {
            engine.addTask(new JobTask());
        }
        ICanceller canceller = engine.setTaskChainCallback(new TaskChainCallbackAdapter() {
            @Override
            public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                Log.e(TAG, "task chain completed, result:" + result.getDataStore().getInt(Job.KEY_JOB_TARGET));
            }
        }).start();
        addCanceller(canceller);
    }

    private void addCanceller(ICanceller canceller) {
        if (canceller != null) {
            mPool.add(canceller.getName());
        }
    }

    @Override
    public void onDestroyView() {
        if (!ObjectUtils.isEmpty(mPool)) {
            XTask.cancelTaskChain(mPool);
        }
        super.onDestroyView();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/MainFragment.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import android.view.KeyEvent;

import com.xuexiang.xtaskdemo.core.BaseContainerFragment;
import com.xuexiang.xtaskdemo.utils.XToastUtils;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xpage.enums.CoreAnim;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xutil.XUtil;
import com.xuexiang.xutil.common.ClickUtils;

/**
 * 主页面
 *
 * @author xuexiang
 * @since 2018/11/7 下午1:16
 */
@Page(name = "XTask", anim = CoreAnim.none)
public class MainFragment extends BaseContainerFragment implements ClickUtils.OnClick2ExitListener {

    @Override
    protected Class[] getPagesClasses() {
        return new Class[]{
                //此处填写fragment
                XTaskStepFragment.class,
                CustomTaskFragment.class,
                UseCaseFragment.class,
                XTaskThreadFragment.class,
                TestThreadPoolFragment.class
        };
    }

    @Override
    protected TitleBar initTitle() {
        return super.initTitle().setLeftClickListener(view -> ClickUtils.exitBy2Click(2000, this));
    }


    /**
     * 菜单、返回键响应
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            ClickUtils.exitBy2Click(2000, this);
        }
        return true;
    }

    @Override
    public void onRetry() {
        XToastUtils.toast("再按一次退出程序");
    }

    @Override
    public void onExit() {
        XUtil.exitApp();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/TestThreadPoolFragment.java
================================================
/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import android.util.Log;

import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.thread.priority.IPriority;
import com.xuexiang.xtask.thread.pool.PriorityThreadPoolExecutor;
import com.xuexiang.xtaskdemo.core.BaseSimpleListFragment;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池测试页面
 *
 * @author xuexiang
 * @since 2019-07-08 00:52
 */
@Page(name = "线程池测试页面")
public class TestThreadPoolFragment extends BaseSimpleListFragment {

    private static final String TAG = "TestFragment";

    @Override
    protected List<String> initSimpleData(List<String> lists) {
        lists.add("优先级线程池测试Runnable的优先级执行");
        lists.add("普通线程池测试Runnable的执行");
        lists.add("测试线程池利用率");
        lists.add("线程优先级");
        return lists;
    }

    @Override
    protected void onItemClick(int position) {
        final Runnable r1 = getRunnable("r1");
        final Runnable r2 = getRunnable("r2");
        final Runnable r3 = getRunnable("r3");
        final Runnable r4 = getRunnable("r4");
        final Runnable r5 = getRunnable("r5");

        switch (position) {
            case 0:
                PriorityThreadPoolExecutor executor = PriorityThreadPoolExecutor.newBuilder(1).build();
                // 优先级大的优先执行
                executor.execute(r5, 1);
                Log.d(TAG, "==== add r5 ====");
                executor.execute(r4, 2);
                Log.d(TAG, "==== add r4 ====");
                executor.execute(r3, 3);
                Log.d(TAG, "==== add r3 ====");
                executor.execute(r2, 4);
                Log.d(TAG, "==== add r2 ====");
                executor.execute(r1, 5);
                Log.d(TAG, "==== add r1 ====");
                break;
            case 1:
                ExecutorService executorService = Executors.newSingleThreadExecutor();
                executorService.execute(r5);
                Log.d(TAG, "==== add r5 ====");
                executorService.execute(r4);
                Log.d(TAG, "==== add r4 ====");
                executorService.execute(r3);
                Log.d(TAG, "==== add r3 ====");
                executorService.execute(r2);
                Log.d(TAG, "==== add r2 ====");
                executorService.execute(r1);
                Log.d(TAG, "==== add r1 ====");
                break;
            case 2:
                Log.d(TAG, "cpu count:" + Runtime.getRuntime().availableProcessors());
                // 任务的最大数量 = maximumPoolSize + BlockingQueue.size, 这里length>30就会报错
                int length = 30;
                ExecutorService fixedThreadPool = new ThreadPoolExecutor(5, 20,
                        30L, TimeUnit.SECONDS,
                        new ArrayBlockingQueue<>(10));
                List<Runnable> list = new ArrayList<>(length);
                for (int i = 0; i < length; i++) {
                    list.add(getRunnable("r" + i));
                }
                for (int i = 0; i < list.size(); i++) {
                    fixedThreadPool.execute(list.get(i));
                }
                break;
            case 3:
                Thread thread1 = new Thread(() -> {
                    Log.e(TAG, "MIN_PRIORITY start...");
                });
                thread1.setPriority(Thread.MIN_PRIORITY);

                Thread thread2 = new Thread(() -> {
                    Log.e(TAG, "NORM_PRIORITY start...");
                });
                thread2.setPriority(Thread.NORM_PRIORITY);

                Thread thread3 = new Thread(() -> {
                    Log.e(TAG, "MAX_PRIORITY start...");
                });
                thread3.setPriority(Thread.MAX_PRIORITY);

                thread1.start();
                thread2.start();
                thread3.start();

                break;
            default:
                break;
        }
    }

    private static Runnable getRunnable(final String name) {

        return new Runnable() {
            @Override
            public void run() {
                Integer priority = getPriority(this);
                if (priority != null) {
                    Log.d(TAG, "==[execute start]== " + name + ", priority=" + priority);
                } else {
                    Log.d(TAG, "==[execute start]== " + name);
                }
                // 模拟复杂处理任务
                // Simulate processing tasks
                int a = 0;
                for (int i = 0; i < 100000000; i++) {
                    a += 1;
                }
                if (priority != null) {
                    Log.d(TAG, "execute end " + name + ", priority=" + priority);
                } else {
                    Log.d(TAG, "execute end " + name);
                }

            }
        };
    }

    private static Integer getPriority(Object o) {
        if (o instanceof IPriority) {
            return ((IPriority) o).priority();
        }
        return null;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/UseCaseFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtaskdemo.core.BaseContainerFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.AppStartFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.ComplexBusinessFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.ConcurrentProcessFragment;

/**
 * @author xuexiang
 * @since 2/23/22 12:21 AM
 */
@Page(name = "应用场景\n列举常用的使用案例")
public class UseCaseFragment extends BaseContainerFragment {

    @Override
    protected Class[] getPagesClasses() {
        return new Class[]{
                AppStartFragment.class,
                ComplexBusinessFragment.class,
                ConcurrentProcessFragment.class
        };
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskStepFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import android.util.Log;

import androidx.annotation.NonNull;

import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.api.TaskChainEngine;
import com.xuexiang.xtask.api.step.ConcurrentGroupTaskStep;
import com.xuexiang.xtask.api.step.SerialGroupTaskStep;
import com.xuexiang.xtask.api.step.XTaskStep;
import com.xuexiang.xtask.core.ITaskChainEngine;
import com.xuexiang.xtask.core.ThreadType;
import com.xuexiang.xtask.core.param.ITaskParam;
import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtask.core.param.impl.TaskParam;
import com.xuexiang.xtask.core.param.impl.TaskResult;
import com.xuexiang.xtask.core.step.impl.TaskChainCallbackAdapter;
import com.xuexiang.xtask.core.step.impl.TaskCommand;
import com.xuexiang.xtask.thread.pool.cancel.ICanceller;
import com.xuexiang.xtaskdemo.core.BaseSimpleListFragment;
import com.xuexiang.xutil.common.ObjectUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 使用XTaskStep可以让你使用起来更方便
 *
 * @author xuexiang
 * @since 1/20/22 12:24 AM
 */
@Page(name = "XTaskStep任务使用\n通过XTaskStep进行简化使用")
public class XTaskStepFragment extends BaseSimpleListFragment {

    private static final String TAG = "TaskFragment";

    private Set<String> mPool = new HashSet<>();

    @Override
    protected List<String> initSimpleData(List<String> lists) {
        lists.add("简单任务链使用");
        lists.add("任务链参数传递");
        lists.add("任务线程控制");
        lists.add("简单的串行任务组使用");
        lists.add("简单的并行任务组使用");
        lists.add("任务执行失败");
        lists.add("任务执行发生异常");
        return lists;
    }

    @Override
    protected void onItemClick(int position) {
        switch (position) {
            case 0:
                doSimpleTaskChain();
                break;
            case 1:
                doParamTaskChain();
                break;
            case 2:
                doThreadTypeTaskChain();
                break;
            case 3:
                doSerialGroupTaskChain();
                break;
            case 4:
                doConcurrentGroupTaskChain();
                break;
            case 5:
                doTaskFailed();
                break;
            case 6:
                doTaskException();
                break;
            default:
                break;
        }

    }

    /**
     * 简单任务链的使用
     */
    private void doSimpleTaskChain() {
        final TaskChainEngine engine = XTask.getTaskChain();
        for (int i = 0; i < 5; i++) {
            engine.addTask(XTask.getTask(new SimpleTaskCommand(1000 * i)));
        }
        ICanceller canceller = engine.setTaskChainCallback(new TaskChainCallbackAdapter() {

            @Override
            public boolean isCallBackOnMainThread() {
                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());
                engine.destroy();
            }

            @Override
            public void onTaskChainError(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                Log.e(TAG, "task chain error");
            }
        }).start();
        addCanceller(canceller);
    }

    /**
     * 任务链参数传递,上一个任务的参数可传递至下一个任务
     */
    private void doParamTaskChain() {
        final TaskChainEngine engine = XTask.getTaskChain();
        engine.setTaskParam(TaskParam.get("chainName", engine.getName()));
        TaskParam taskParam = TaskParam.get("param1", 100)
                .put("param2", true);
        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);
                    }
                }));
        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());
                }
            }
        }).start();
        addCanceller(canceller);
    }

    /**
     * 任务线程控制
     */
    private void doThreadTypeTaskChain() {
        final TaskChainEngine engine = XTask.getTaskChain();
        ICanceller canceller = engine.addTask(XTask.getTask(new SimpleTaskCommand(1000), ThreadType.ASYNC))
                .addTask(XTask.getTask(new SimpleTaskCommand(1000), ThreadType.ASYNC_EMERGENT))
                .addTask(XTask.getTask(new SimpleTaskCommand(200), ThreadType.MAIN))
                .addTask(XTask.getTask(new SimpleTaskCommand(1000), ThreadType.ASYNC_IO))
                .addTask(XTask.getTask(new SimpleTaskCommand(1000), ThreadType.SYNC))
                .addTask(XTask.getTask(new SimpleTaskCommand(1000), ThreadType.ASYNC_BACKGROUND))
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainStart(@NonNull ITaskChainEngine engine) {
                        Log.e(TAG, "task chain start, thread:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        Log.e(TAG, "task chain completed, thread:" + Thread.currentThread().getName());
                    }
                }).start();
        addCanceller(canceller);
    }

    /**
     * 简单的串行任务组使用
     */
    private void doSerialGroupTaskChain() {
        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);
    }

    /**
     * 简单的并行任务组使用
     */
    private void doConcurrentGroupTaskChain() {
        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);
    }


    /**
     * 任务执行失败,整个链路都停止工作
     */
    private void doTaskFailed() {
        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));
        }
        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());
            }

            @Override
            public void onTaskChainError(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                Log.e(TAG, "task chain error, " + result.getDetailMessage());
            }
        }).start();
        addCanceller(canceller);
    }

    private void doTaskException() {
        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() throws Exception {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (finalI == 2) {
                        throw new Exception("执行出现异常!");
                    }
                }
            }));
        }
        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());
            }

            @Override
            public void onTaskChainError(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                Log.e(TAG, "task chain error, " + result.getDetailMessage());
            }
        }).start();
        addCanceller(canceller);
    }

    private void addCanceller(ICanceller canceller) {
        if (canceller != null) {
            mPool.add(canceller.getName());
        }
    }

    private static class SimpleTaskCommand extends TaskCommand {

        private long mDuring;

        private SimpleTaskCommand(long during) {
            mDuring = during;
        }

        @Override
        public void run() {
            Log.e(TAG, getName() + "  start...thread:" + Thread.currentThread().getName());
            try {
                Thread.sleep(mDuring);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e(TAG, getName() + "  end...");
        }
    }

    @Override
    public void onDestroyView() {
        if (!ObjectUtils.isEmpty(mPool)) {
            XTask.cancelTaskChain(mPool);
        }
        super.onDestroyView();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskThreadFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment;

import android.util.Log;

import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.thread.pool.cancel.ICancelable;
import com.xuexiang.xtask.thread.utils.CancelUtils;
import com.xuexiang.xtaskdemo.core.BaseSimpleListFragment;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 使用XTask进行线程池操作
 *
 * @author xuexiang
 * @since 3/20/22 2:22 AM
 */
@Page(name = "XTask线程池使用\nXTask拥有丰富的线程调度方法")
public class XTaskThreadFragment extends BaseSimpleListFragment {

    private static final String TAG = "XTaskThreadFragment";

    private List<ICancelable> mCancelableList = new ArrayList<>();

    @Override
    protected List<String> initSimpleData(List<String> lists) {
        lists.add("普通异步执行");
        lists.add("紧急异步执行");
        lists.add("后台异步执行");
        lists.add("优先级异步执行");
        lists.add("主线程延迟执行");
        lists.add("子线程延迟执行");
        lists.add("周期执行(固定间期)");
        lists.add("周期执行(固定延期)");
        return lists;
    }

    @Override
    protected void onItemClick(int position) {
        switch (position) {
            case 0:
                doNormalAsync();
                break;
            case 1:
                doEmergentAsync();
                break;
            case 2:
                doBackgroundAsync();
                break;
            case 3:
                doPriorityAsync();
                break;
            case 4:
                doDelayOnMainThread();
                break;
            case 5:
                doDelay();
                break;
            case 6:
                doPollingFixedRate();
                break;
            case 7:
                doPollingFixedDelay();
                break;
            default:
                break;
        }
    }

    private void doNormalAsync() {
        Log.e(TAG, "doNormalAsync start...");
        ICancelable cancelable = XTask.submit(() -> {
            Log.e(TAG, "Async task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        });
        mCancelableList.add(cancelable);
    }

    private void doEmergentAsync() {
        Log.e(TAG, "doEmergentAsync start...");
        ICancelable cancelable = XTask.emergentSubmit(() -> {
            Log.e(TAG, "Emergent task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        });
        mCancelableList.add(cancelable);
    }

    private void doBackgroundAsync() {
        Log.e(TAG, "doBackgroundAsync start...");
        ICancelable cancelable = XTask.backgroundSubmit(() -> {
            Log.e(TAG, "Background task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        });
        mCancelableList.add(cancelable);
    }

    private void doPriorityAsync() {
        Log.e(TAG, "doPriorityAsync start...");
        ICancelable cancelable = XTask.submit(() -> {
            Log.e(TAG, "Priority task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        }, 10);
        mCancelableList.add(cancelable);
    }

    private void doDelayOnMainThread() {
        Log.e(TAG, "doDelayOnMainThread start...");
        ICancelable cancelable = XTask.postToMainDelay(() -> {
            Log.e(TAG, "Delay task start, thread:" + Thread.currentThread().getName());
        }, 2000);
        mCancelableList.add(cancelable);
    }

    private void doDelay() {
        Log.e(TAG, "doDelay start...");
        ICancelable cancelable = XTask.schedule(() -> {
            Log.e(TAG, "Delay task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        }, 2, TimeUnit.SECONDS);
        mCancelableList.add(cancelable);
    }

    private void doPollingFixedRate() {
        Log.e(TAG, "doPollingFixedRate start...");
        ICancelable cancelable = XTask.scheduleAtFixedRate(() -> {
            Log.e(TAG, "FixedRate task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        }, 0, 2, TimeUnit.SECONDS);
        mCancelableList.add(cancelable);
    }

    private void doPollingFixedDelay() {
        Log.e(TAG, "doPollingFixedDelay start...");
        ICancelable cancelable = XTask.scheduleWithFixedDelay(() -> {
            Log.e(TAG, "FixedDelay task start, thread:" + Thread.currentThread().getName());
            mockProcess(2000);
        }, 0, 2, TimeUnit.SECONDS);
        mCancelableList.add(cancelable);
    }

    /**
     * 模拟执行
     *
     * @param time 模拟执行所需要的时间
     */
    public void mockProcess(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroyView() {
        CancelUtils.cancel(mCancelableList);
        super.onDestroyView();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/Job.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.task;

import android.util.Log;

import androidx.annotation.NonNull;

import com.xuexiang.xtask.core.param.ITaskParam;
import com.xuexiang.xtask.core.param.impl.TaskResult;
import com.xuexiang.xtask.core.step.ITaskStepController;
import com.xuexiang.xtaskdemo.fragment.CustomTaskFragment;

/**
 * 模拟复杂的任务
 *
 * @author xuexiang
 * @since 2/9/22 11:22 PM
 */
public class Job implements Runnable {

    public static final String KEY_JOB_TARGET = "key_job_target";

    private ITaskStepController mController;

    public Job(@NonNull ITaskStepController controller) {
        mController = controller;
    }

    @Override
    public void run() {
        ITaskParam taskParam = mController.getTaskParam();
        int target = taskParam.getInt(KEY_JOB_TARGET);
        Log.e(CustomTaskFragment.TAG, "Job is running..., target:" + target);
        // 模拟耗时
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        taskParam.put(KEY_JOB_TARGET, target + 10);
        mController.notifyTaskSucceed(TaskResult.succeed());
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/JobTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.task;

import com.xuexiang.xtask.api.step.SimpleTaskStep;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 模拟复杂任务
 *
 * @author xuexiang
 * @since 2/9/22 11:22 PM
 */
public class JobTask extends SimpleTaskStep {

    private static final AtomicInteger TASK_NUMBER = new AtomicInteger(1);

    /**
     * 构造方法
     */
    public JobTask() {
        super("CallBackTask-" + TASK_NUMBER.getAndIncrement());
    }


    @Override
    public void doTask() throws Exception {
        new Job(this).run();
    }

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


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepATask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.task;

import android.util.Log;

import com.xuexiang.xtask.core.param.impl.TaskResult;
import com.xuexiang.xtask.core.step.impl.AbstractTaskStep;
import com.xuexiang.xtaskdemo.fragment.CustomTaskFragment;

/**
 * 步骤A任务
 *
 * @author xuexiang
 * @since 2/9/22 1:37 AM
 */
public class StepATask extends AbstractTaskStep {

    public static final String KEY_TOTAL = "total";

    @Override
    public void doTask() throws Exception {
        Log.e(CustomTaskFragment.TAG, "doing StepA task!");
        // 增加参数
        getTaskParam().put(KEY_TOTAL, 10);
        // 通知任务链任务完成
        notifyTaskSucceed(TaskResult.succeed());
    }

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


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepBTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.task;

import android.util.Log;

import com.xuexiang.xtask.core.param.impl.TaskResult;
import com.xuexiang.xtask.core.step.impl.AbstractTaskStep;
import com.xuexiang.xtaskdemo.fragment.CustomTaskFragment;

/**
 * 步骤B任务
 *
 * @author xuexiang
 * @since 2/9/22 1:42 AM
 */
public class StepBTask extends AbstractTaskStep {

    @Override
    public void doTask() throws Exception {
        Log.e(CustomTaskFragment.TAG, "doing StepB task!");
        // 获取参数进行处理
        int total = getTaskParam().getInt(StepATask.KEY_TOTAL) + 20;
        Log.e(CustomTaskFragment.TAG, "total:" + total);
        // 更新结果
        getTaskParam().put(StepATask.KEY_TOTAL, total);
        notifyTaskSucceed(TaskResult.succeed());
    }

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


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/AppStartFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase;

import android.view.View;

import androidx.annotation.NonNull;

import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.api.step.ConcurrentGroupTaskStep;
import com.xuexiang.xtask.core.ITaskChainEngine;
import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtask.core.step.impl.TaskChainCallbackAdapter;
import com.xuexiang.xtask.core.step.impl.TaskCommand;
import com.xuexiang.xtaskdemo.R;
import com.xuexiang.xtaskdemo.core.BaseFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.job.LongTimeJob;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.job.SingleJob;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.job.TopPriorityJob;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.task.AsyncInitTask;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.task.MainInitTask;
import com.xuexiang.xui.widget.textview.LoggerTextView;

import butterknife.BindView;
import butterknife.OnClick;

/**
 * 应用冷启动优化
 * <p>
 * 所谓的应用冷启动优化,最主要的就是减少应用在初始化应用在主线程中所占用的时间。
 * 针对一些耗时的操作,我们常用的优化策略是:
 * 1.同步主线程执行 -> 异步子线程执行
 * 2.串行操作 -> 并行操作
 * 3.预加载 -> 懒加载
 * 4.业务流程优化(按业务的优先级调整执行顺序)
 * 5.数据结构优化(减少加载时间)
 *
 * @author xuexiang
 * @since 2/23/22 12:26 AM
 */
@Page(name = "应用冷启动优化")
public class AppStartFragment extends BaseFragment {

    @BindView(R.id.logger)
    LoggerTextView logger;

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_usecase_template;
    }

    @Override
    protected void initViews() {


    }

    @SingleClick
    @OnClick({R.id.btn_before_improve, R.id.btn_after_improve})
    public void onViewClicked(View view) {
        clearLog();
        log("开始执行任务...");
        final long startTime = System.currentTimeMillis();
        switch (view.getId()) {
            case R.id.btn_before_improve:
                doJobBeforeImprove(startTime);
                break;
            case R.id.btn_after_improve:
                doJobAfterImprove(startTime);
                break;
            default:
                break;
        }
    }


    /**
     * 优化前的写法, 这里仅是演示模拟,实际的可能更复杂
     */
    private void doJobBeforeImprove(long startTime) {
        new TopPriorityJob(logger).doJob();
        for (int i = 0; i < 4; i++) {
            new SingleJob((i + 1), logger).doJob();
        }
        new LongTimeJob(logger).doJob();
        log("任务执行完毕,总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
    }

    /**
     * 优化后的写法, 这里仅是演示模拟,实际的可能更复杂
     */
    private void doJobAfterImprove(final long startTime) {
        ConcurrentGroupTaskStep groupTaskStep = XTask.getConcurrentGroupTask();
        for (int i = 0; i < 4; i++) {
            int finalI = i;
            groupTaskStep.addTask(XTask.getTask(new TaskCommand() {
                @Override
                public void run() throws Exception {
                    new SingleJob((finalI + 1), logger).doJob();
                }
            }));
        }
        XTask.getTaskChain()
                .addTask(new MainInitTask(logger))
                .addTask(groupTaskStep)
                .addTask(new AsyncInitTask(logger))
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        log("任务完全执行完毕,总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                    }
                }).start();
        log("主线程任务执行完毕,总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
    }

    public void log(String logContent) {
        if (logger != null) {
            logger.logSuccess(logContent);
        }
    }

    public void clearLog() {
        if (logger != null) {
            logger.clearLog();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        XTask.cancelAllTaskChain();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ComplexBusinessFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase;

import android.util.Pair;
import android.view.View;

import androidx.annotation.NonNull;

import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.core.ITaskChainEngine;
import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtask.core.param.impl.TaskParam;
import com.xuexiang.xtask.core.step.impl.TaskChainCallbackAdapter;
import com.xuexiang.xtaskdemo.R;
import com.xuexiang.xtaskdemo.core.BaseFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductFactory;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.GetProductInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.GivePriceProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.PublicProductProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.SearchFactoryProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.GetProductInfoTask;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.GivePriceTask;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.ProductTaskConstants;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.PublicProductTask;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.SearchFactoryTask;
import com.xuexiang.xui.widget.textview.LoggerTextView;
import com.xuexiang.xutil.system.AppExecutors;

import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

/**
 * 复杂业务流程处理
 *
 * 案例[高仿网红产品]的流程如下:
 * 1.获取产品信息 -> 2.查询可生产的工厂 -> 3.联系工厂生产产品 -> 4.送去市场部门评估售价 -> 5.产品上市
 *
 * @author xuexiang
 * @since 3/18/22 11:28 PM
 */
@Page(name = "复杂业务流程处理")
public class ComplexBusinessFragment extends BaseFragment {

    @BindView(R.id.logger)
    LoggerTextView logger;

    private String productId = "123456";

    private Disposable disposable;

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_usecase_compare;
    }

    @Override
    protected void initViews() {

    }

    @SingleClick
    @OnClick({R.id.btn_normal, R.id.btn_rxjava, R.id.btn_xtask})
    public void onViewClicked(View view) {
        clearLog();
        log("开始仿冒生产网红产品...");
        final long startTime = System.currentTimeMillis();
        switch (view.getId()) {
            case R.id.btn_normal:
                doBusinessNormal(startTime);
                break;
            case R.id.btn_rxjava:
                doBusinessRxJava(startTime);
                break;
            case R.id.btn_xtask:
                doBusinessXTask(startTime);
                break;
            default:
                break;
        }
    }

    /**
     * 普通的接口回调写法, 这里仅是演示模拟,实际的可能更复杂
     * 流程如下:
     * 1.获取产品信息 -> 2.查询可生产的工厂 -> 3.联系工厂生产产品 -> 4.送去市场部门评估售价 -> 5.产品上市
     */
    private void doBusinessNormal(final long startTime) {
        AppExecutors.get().singleIO().execute(() -> {
            // 1.获取产品信息
            new GetProductInfoProcessor(logger, productId).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<ProductInfo>() {
                @Override
                public void onSuccess(final ProductInfo productInfo) {
                    // 2.查询可生产的工厂
                    new SearchFactoryProcessor(logger, productInfo).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<ProductFactory>() {
                        @Override
                        public void onSuccess(final ProductFactory factory) {
                            // 3.联系工厂生产产品
                            log("开始生产产品...");
                            Product product = factory.produce(productInfo);
                            // 4.送去市场部门评估售价
                            new GivePriceProcessor(logger, product).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<Product>() {
                                @Override
                                public void onSuccess(Product product) {
                                    // 5.产品上市
                                    PublicProductProcessor publicProductProcessor = new PublicProductProcessor(logger, product);
                                    publicProductProcessor.setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<Product>() {
                                        @Override
                                        public void onSuccess(Product product) {
                                            log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                                            log("仿冒生产网红产品完成, " + product);
                                        }
                                    }).process();
                                }
                            }).process();
                        }
                    }).process();
                }
            }).process();
        });
    }


    /**
     * RxJava写法, 这里仅是演示模拟,实际的可能更复杂
     * 流程如下:
     * 1.获取产品信息 -> 2.查询可生产的工厂 -> 3.联系工厂生产产品 -> 4.送去市场部门评估售价 -> 5.产品上市
     */
    private void doBusinessRxJava(final long startTime) {
        disposable = Observable.just(productId)
                // 1.获取产品信息
                .map(id -> new GetProductInfoProcessor(logger, id).process())
                // 2.查询可生产的工厂
                .map(productInfo -> new Pair<>(new SearchFactoryProcessor(logger, productInfo).process(), productInfo))
                .map(productPair -> {
                    // 3.联系工厂生产产品
                    log("开始生产产品...");
                    Product product = productPair.first.produce(productPair.second);
                    // 4.送去市场部门评估售价
                    return new GivePriceProcessor(logger, product).process();
                })
                // 5.产品上市
                .map(product -> new PublicProductProcessor(logger, product).process())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(product -> {
                    log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                    log("仿冒生产网红产品完成, " + product);
                });
    }


    /**
     * XTask写法, 这里仅是演示模拟,实际的可能更复杂
     * 流程如下:
     * 1.获取产品信息 -> 2.查询可生产的工厂 -> 3.联系工厂生产产品 -> 4.送去市场部门评估售价 -> 5.产品上市
     */
    private void doBusinessXTask(final long startTime) {
        XTask.getTaskChain()
                .setTaskParam(TaskParam.get(ProductTaskConstants.KEY_PRODUCT_ID, productId))
                // 1.获取产品信息
                .addTask(new GetProductInfoTask(logger))
                // 2.查询可生产的工厂, 3.联系工厂生产产品
                .addTask(new SearchFactoryTask(logger))
                // 4.送去市场部门评估售价
                .addTask(new GivePriceTask(logger))
                // 5.产品上市
                .addTask(new PublicProductTask(logger))
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                        Product product = result.getDataStore().getObject(ProductTaskConstants.KEY_PRODUCT, Product.class);
                        log("仿冒生产网红产品完成, " + product);
                    }
                }).start();
    }


    public void log(String logContent) {
        if (logger != null) {
            logger.logSuccess(logContent);
        }
    }

    public void clearLog() {
        if (logger != null) {
            logger.clearLog();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        XTask.cancelAllTaskChain();
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ConcurrentProcessFragment.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase;

import android.view.View;

import androidx.annotation.NonNull;

import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xtask.XTask;
import com.xuexiang.xtask.core.ITaskChainEngine;
import com.xuexiang.xtask.core.ThreadType;
import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtask.core.param.impl.TaskParam;
import com.xuexiang.xtask.core.step.impl.TaskChainCallbackAdapter;
import com.xuexiang.xtaskdemo.R;
import com.xuexiang.xtaskdemo.core.BaseFragment;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.task.ProductTaskConstants;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.BriefInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.FactoryInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.PriceInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.PromotionInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.RichInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor.GetBriefInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor.GetFactoryInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor.GetPriceInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor.GetPromotionInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor.GetRichInfoProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.task.GetBriefInfoTask;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.task.GetFactoryInfoTask;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.task.GetPriceInfoTask;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.task.GetPromotionInfoTask;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.task.GetRichInfoTask;
import com.xuexiang.xui.widget.textview.LoggerTextView;
import com.xuexiang.xutil.system.AppExecutors;

import java.util.concurrent.CountDownLatch;

import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

/**
 * 复杂并发任务处理
 * <p>
 * 案例[展示商品详细信息]的流程如下:
 * <p>
 * 1.根据商品的唯一号ID获取商品简要信息
 * 2.获取商品的详细信息:
 * 2.1 获取商品的生产信息
 * 2.2 获取商品的价格信息
 * 2.3 获取商品的促销信息
 * 2.4 获取商品的富文本信息
 * 3.进行商品信息的展示
 *
 * @author xuexiang
 * @since 3/21/22 10:57 PM
 */
@Page(name = "复杂并发任务处理")
public class ConcurrentProcessFragment extends BaseFragment {

    @BindView(R.id.logger)
    LoggerTextView logger;

    private String productId = "123456";

    private Disposable disposable;

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_usecase_compare;
    }


    @Override
    protected void initViews() {

    }

    @SingleClick
    @OnClick({R.id.btn_normal, R.id.btn_rxjava, R.id.btn_xtask})
    public void onViewClicked(View view) {
        clearLog();
        log("开始查询商品信息...");
        final long startTime = System.currentTimeMillis();
        switch (view.getId()) {
            case R.id.btn_normal:
                queryInfoNormal(startTime, productId);
                break;
            case R.id.btn_rxjava:
                queryInfoRxJava(startTime, productId);
                break;
            case R.id.btn_xtask:
                queryInfoXTask(startTime, productId);
                break;
            default:
                break;
        }
    }


    /**
     * 普通的接口回调写法, 这里仅是演示模拟,实际的可能更复杂
     */
    private void queryInfoNormal(final long startTime, String productId) {
        AppExecutors.get().singleIO().execute(() -> {
            new GetBriefInfoProcessor(logger, productId).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<BriefInfo>() {
                @Override
                public void onSuccess(BriefInfo briefInfo) {
                    final Product product = new Product(briefInfo);
                    CountDownLatch latch = new CountDownLatch(4);

                    // 2.1 获取商品的生产信息
                    AppExecutors.get().networkIO().execute(() -> {
                        new GetFactoryInfoProcessor(logger, product.getFactoryId()).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<FactoryInfo>() {
                            @Override
                            public void onSuccess(FactoryInfo result) {
                                product.setFactory(result);
                                latch.countDown();
                            }
                        }).process();
                    });
                    // 2.2 获取商品的价格信息
                    AppExecutors.get().networkIO().execute(() -> {
                        new GetPriceInfoProcessor(logger, product.getPriceId()).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<PriceInfo>() {
                            @Override
                            public void onSuccess(PriceInfo result) {
                                product.setPrice(result);
                                latch.countDown();
                            }
                        }).process();
                    });
                    // 2.3 获取商品的促销信息
                    AppExecutors.get().networkIO().execute(() -> {
                        new GetPromotionInfoProcessor(logger, product.getPromotionId()).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<PromotionInfo>() {
                            @Override
                            public void onSuccess(PromotionInfo result) {
                                product.setPromotion(result);
                                latch.countDown();
                            }
                        }).process();
                    });
                    // 2.4 获取商品的富文本信息
                    AppExecutors.get().networkIO().execute(() -> {
                        new GetRichInfoProcessor(logger, product.getRichId()).setProcessorCallback(new AbstractProcessor.ProcessorCallbackAdapter<RichInfo>() {
                            @Override
                            public void onSuccess(RichInfo result) {
                                product.setRich(result);
                                latch.countDown();
                            }
                        }).process();
                    });
                    try {
                        latch.await();
                        log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                        log("查询商品信息完成, " + product);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).process();
        });
    }

    /**
     * RxJava写法, 这里仅是演示模拟,实际的可能更复杂
     */
    private void queryInfoRxJava(final long startTime, String productId) {
        disposable = Observable.just(productId)
                // 1.获取商品简要信息
                .map(id -> new GetBriefInfoProcessor(logger, id).process())
                .map(Product::new)
                .flatMap(product ->
                        Observable.zip(
                                // 2.1 获取商品的生产信息
                                Observable.fromCallable(() -> new GetFactoryInfoProcessor(logger, product.getFactoryId()).process()).subscribeOn(Schedulers.io()),
                                // 2.2 获取商品的价格信息
                                Observable.fromCallable(() -> new GetPriceInfoProcessor(logger, product.getPriceId()).process()).subscribeOn(Schedulers.io()),
                                // 2.3 获取商品的促销信息
                                Observable.fromCallable(() -> new GetPromotionInfoProcessor(logger, product.getPromotionId()).process()).subscribeOn(Schedulers.io()),
                                // 2.4 获取商品的富文本信息
                                Observable.fromCallable(() -> new GetRichInfoProcessor(logger, product.getRichId()).process()).subscribeOn(Schedulers.io()), (factoryInfo, priceInfo, promotionInfo, richInfo) -> product.setFactory(factoryInfo)
                                        .setPrice(priceInfo)
                                        .setPromotion(promotionInfo)
                                        .setRich(richInfo)
                        )
                )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(product -> {
                    log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                    log("查询商品信息完成, " + product);
                });
    }

    /**
     * XTask写法, 这里仅是演示模拟,实际的可能更复杂
     */
    private void queryInfoXTask(final long startTime, String productId) {
        XTask.getTaskChain()
                .setTaskParam(TaskParam.get(ProductTaskConstants.KEY_PRODUCT_ID, productId))
                // 1.获取商品简要信息
                .addTask(new GetBriefInfoTask(logger))
                .addTask(XTask.getConcurrentGroupTask(ThreadType.SYNC)
                        // 2.1 获取商品的生产信息
                        .addTask(new GetFactoryInfoTask(logger))
                        // 2.2 获取商品的价格信息
                        .addTask(new GetPriceInfoTask(logger))
                        // 2.3 获取商品的促销信息
                        .addTask(new GetPromotionInfoTask(logger))
                        // 2.4 获取商品的富文本信息
                        .addTask(new GetRichInfoTask(logger)))
                .setTaskChainCallback(new TaskChainCallbackAdapter() {
                    @Override
                    public void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull ITaskResult result) {
                        log("总共耗时:" + (System.currentTimeMillis() - startTime) + "ms");
                        Product product = result.getDataStore().getObject(ProductTaskConstants.KEY_PRODUCT, Product.class);
                        log("查询商品信息完成, " + product);
                    }
                }).start();
    }


    public void log(String logContent) {
        if (logger != null) {
            logger.logSuccess(logContent);
        }
    }

    public void clearLog() {
        if (logger != null) {
            logger.clearLog();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        XTask.cancelAllTaskChain();
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/AbstractMockJob.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.job;

import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 模拟任务
 *
 * @author xuexiang
 * @since 2/23/22 12:47 AM
 */
public abstract class AbstractMockJob {

    private LoggerTextView mLogger;

    public AbstractMockJob(LoggerTextView logger) {
        mLogger = logger;
    }

    /**
     * 模拟执行任务
     */
    public abstract void doJob();

    public void log(String logContent) {
        if (mLogger != null) {
            mLogger.logNormal(logContent);
        }
    }


    /**
     * 模拟执行
     *
     * @param time 模拟执行所需要的时间
     */
    public void mockProcess(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/LongTimeJob.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.job;

import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 耗时任务,比如第三方依赖库的初始化、大数据的预加载、磁盘读写操作等
 *
 * @author xuexiang
 * @since 2/23/22 1:02 AM
 */
public class LongTimeJob extends AbstractMockJob {

    public LongTimeJob(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doJob() {
        log("[耗时任务]开始执行...");
        mockProcess(1000);
        log("[耗时任务]执行完毕!");
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/SingleJob.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.job;

import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 单独的任务,没有执行上的先后顺序. 例如:非核心数据的加载。
 *
 * @author xuexiang
 * @since 2/23/22 1:16 AM
 */
public class SingleJob extends AbstractMockJob {

    private int mIndex;

    public SingleJob(int index, LoggerTextView logger) {
        super(logger);
        mIndex = index;
    }

    @Override
    public void doJob() {
        log("[单独的任务" + mIndex + "]开始执行...");
        mockProcess(200);
        log("[单独的任务" + mIndex + "]执行完毕!");
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/TopPriorityJob.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.job;

import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 最高优先级的事务,比如核心框架的初始化,关键数据的初始化等
 *
 * @author xuexiang
 * @since 2/23/22 12:51 AM
 */
public class TopPriorityJob extends AbstractMockJob {

    public TopPriorityJob(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doJob() {
        log("[最高优先级的任务]开始执行...");
        mockProcess(50);
        log("[最高优先级的任务]执行完毕!");
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/AsyncInitTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.task;

import androidx.annotation.NonNull;

import com.xuexiang.xtask.api.step.SimpleTaskStep;
import com.xuexiang.xtask.core.ThreadType;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.job.LongTimeJob;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 异步初始化任务
 * 放一些优先级不是很高的、耗时的初始化任务
 *
 * @author xuexiang
 * @since 2/23/22 1:42 AM
 */
public class AsyncInitTask extends SimpleTaskStep {

    private LoggerTextView mLogger;

    public AsyncInitTask(LoggerTextView logger) {
        mLogger = logger;
    }

    @Override
    public void doTask() throws Exception {
        // 执行耗时任务
        new LongTimeJob(mLogger).doJob();
    }

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

    @NonNull
    @Override
    public ThreadType getThreadType() {
        // 任务的优先级不高,使用异步子线程执行
        return ThreadType.ASYNC;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/MainInitTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.appstart.task;

import androidx.annotation.NonNull;

import com.xuexiang.xtask.api.step.SimpleTaskStep;
import com.xuexiang.xtask.core.ThreadType;
import com.xuexiang.xtaskdemo.fragment.usecase.appstart.job.TopPriorityJob;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 主要初始化任务,放在第一位执行, 执行最高优先级的事务
 *
 * @author xuexiang
 * @since 2/23/22 1:34 AM
 */
public class MainInitTask extends SimpleTaskStep {

    private LoggerTextView mLogger;

    public MainInitTask(LoggerTextView logger) {
        mLogger = logger;
    }

    @Override
    public void doTask() throws Exception {
        // 执行最高优先级的事务
        new TopPriorityJob(mLogger).doJob();
    }


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

    @NonNull
    @Override
    public ThreadType getThreadType() {
        // 任务优先级较高,执行有前后依赖,因此将任务放在第一位使用同步主线程执行
        return ThreadType.SYNC;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/Product.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.entity;

/**
 * 产品
 *
 * @author xuexiang
 * @since 2/25/22 1:17 AM
 */
public class Product {

    private ProductInfo info;

    private String address;

    private String price;

    private String publicTime;

    public Product(ProductInfo info, String address) {
        this.info = info;
        this.address = address;
    }

    public ProductInfo getInfo() {
        return info;
    }

    public Product setInfo(ProductInfo info) {
        this.info = info;
        return this;
    }

    public String getAddress() {
        return address;
    }

    public Product setAddress(String address) {
        this.address = address;
        return this;
    }

    public String getPrice() {
        return price;
    }

    public Product setPrice(String price) {
        this.price = price;
        return this;
    }

    public String getPublicTime() {
        return publicTime;
    }


    public Product setPublicTime(String publicTime) {
        this.publicTime = publicTime;
        return this;
    }

    @Override
    public String toString() {
        return "产品信息:" + info + ", 产地:" + address + ", 价格:" + price + ", 上市日前:" + publicTime;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductFactory.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.entity;

/**
 * 产品工厂
 *
 * @author xuexiang
 * @since 2/25/22 1:15 AM
 */
public class ProductFactory {

    private String id;

    private String address;

    public ProductFactory(String id, String address) {
        this.id = id;
        this.address = address;
    }

    public Product produce(ProductInfo info) {
        return new Product(info, address);
    }

    public String getId() {
        return id;
    }

    public ProductFactory setId(String id) {
        this.id = id;
        return this;
    }

    public String getAddress() {
        return address;
    }

    public ProductFactory setAddress(String address) {
        this.address = address;
        return this;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.entity;

/**
 * 产品信息
 *
 * @author xuexiang
 * @since 2/25/22 12:40 AM
 */
public class ProductInfo {
    /**
     * 编号
     */
    private String id;
    /**
     * 品牌
     */
    private String brand;
    /**
     * 质量
     */
    private String quality;

    public ProductInfo(String id) {
        this.id = id;
    }

    public ProductInfo(String id, String brand, String quality) {
        this.id = id;
        this.brand = brand;
        this.quality = quality;
    }

    public String getId() {
        return id;
    }

    public ProductInfo setId(String id) {
        this.id = id;
        return this;
    }

    public String getBrand() {
        return brand;
    }

    public ProductInfo setBrand(String brand) {
        this.brand = brand;
        return this;
    }

    public String getQuality() {
        return quality;
    }

    public ProductInfo setQuality(String quality) {
        this.quality = quality;
        return this;
    }

    @Override
    public String toString() {
        return "id:" + id + ", 品牌:" + brand + ", 品质:" + quality;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/AbstractProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.processor;

import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 抽象处理器
 *
 * @author xuexiang
 * @since 2/25/22 12:28 AM
 */
public abstract class AbstractProcessor<T> {

    private LoggerTextView mLogger;

    private IProcessorCallback<T> mCallback;


    public AbstractProcessor(LoggerTextView logger) {
        mLogger = logger;
    }

    public AbstractProcessor setProcessorCallback(IProcessorCallback<T> callback) {
        mCallback = callback;
        return this;
    }

    /**
     * 处理任务
     *
     * @return 返回的结果
     */
    public abstract T process();

    public void log(String logContent) {
        if (mLogger != null) {
            mLogger.logNormal(logContent);
        }
    }

    public void onProcessSuccess(T t) {
        if (mCallback != null) {
            mCallback.onSuccess(t);
        }
    }

    public void onProcessFailed(String error) {
        if (mCallback != null) {
            mCallback.onFailed(error);
        }
    }

    /**
     * 模拟执行
     *
     * @param time 模拟执行所需要的时间
     */
    public void mockProcess(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public abstract static class ProcessorCallbackAdapter<T> implements IProcessorCallback<T> {
        @Override
        public void onFailed(String error) {

        }
    }

    public interface IProcessorCallback<T> {
        /**
         * 处理成功
         *
         * @param result 结果
         */
        void onSuccess(T result);

        /**
         * 处理失败
         *
         * @param error 错误信息
         */
        void onFailed(String error);
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GetProductInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 1.获取产品信息
 *
 * @author xuexiang
 * @since 2/25/22 12:34 AM
 */
public class GetProductInfoProcessor extends AbstractProcessor<ProductInfo> {

    private String id;

    public GetProductInfoProcessor(LoggerTextView logger, String id) {
        super(logger);
        this.id = id;
    }

    @Override
    public ProductInfo process() {
        log("[获取产品信息]开始执行...");
        ProductInfo info = getProductInfoById(id);
        log("[获取产品信息]执行完毕!");
        onProcessSuccess(info);
        return info;
    }

    private ProductInfo getProductInfoById(String id) {
        // 模拟耗费的时间
        mockProcess(500);
        return new ProductInfo(id, "品牌A", "高品质");
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GivePriceProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 3.评估产品,给出价格
 * @author xuexiang
 * @since 2/25/22 1:36 AM
 */
public class GivePriceProcessor extends AbstractProcessor<Product> {

    private Product product;

    public GivePriceProcessor(LoggerTextView logger, Product product) {
        super(logger);
        this.product = product;
    }

    @Override
    public Product process() {
        log("[评估产品价格]开始执行...");
        String price = givePrice(product);
        product.setPrice(price);
        log("[评估产品价格]执行完毕!");
        onProcessSuccess(product);
        return product;
    }

    private String givePrice(Product product) {
        // 模拟耗费的时间
        mockProcess(100);
        return "45¥";
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/PublicProductProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductFactory;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 4.产品发布
 *
 * @author xuexiang
 * @since 2/25/22 1:50 AM
 */
public class PublicProductProcessor extends AbstractProcessor<Product> {

    private Product product;

    public PublicProductProcessor(LoggerTextView logger, Product product) {
        super(logger);
        this.product = product;
    }

    public PublicProductProcessor(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public Product process() {
        log("[产品发布]开始执行...");
        String time = getPublicPlan(product);
        product.setPublicTime(time);
        log("[产品发布]执行完毕!");
        onProcessSuccess(product);
        return product;
    }

    private String getPublicPlan(Product product) {
        // 模拟耗费的时间
        mockProcess(400);
        return "2022年2月22日22时22分22秒";
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/SearchFactoryProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductFactory;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 2.查找相关的工厂
 *
 * @author xuexiang
 * @since 2/25/22 1:13 AM
 */
public class SearchFactoryProcessor extends AbstractProcessor<ProductFactory> {

    private ProductInfo info;

    public SearchFactoryProcessor(LoggerTextView logger, ProductInfo info) {
        super(logger);
        this.info = info;
    }

    @Override
    public ProductFactory process() {
        log("[查找相关工厂]开始执行...");
        ProductFactory factory = searchFactoryByBrand(info.getBrand());
        log("[查找相关工厂]执行完毕!");
        onProcessSuccess(factory);
        return factory;
    }

    private ProductFactory searchFactoryByBrand(String brand) {
        // 模拟耗费的时间
        mockProcess(300);
        return new ProductFactory(brand, "南京市江宁区秣陵街道xxx街区");
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/AbstractTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

import com.xuexiang.xtask.api.step.SimpleTaskStep;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 基础抽象任务
 *
 * @author xuexiang
 * @since 2/25/22 2:18 AM
 */
public abstract class AbstractTask extends SimpleTaskStep {

    protected LoggerTextView mLogger;

    public AbstractTask(LoggerTextView logger) {
        mLogger = logger;
    }

    public void log(String logContent) {
        if (mLogger != null) {
            mLogger.logSuccess(logContent);
        }
    }

    @Override
    protected boolean isAutoNotify() {
        // 这里进行手动控制
        return false;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GetProductInfoTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.GetProductInfoProcessor;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 1.获取产品信息
 *
 * @author xuexiang
 * @since 2/25/22 2:07 AM
 */
public class GetProductInfoTask extends AbstractTask {

    public GetProductInfoTask(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doTask() throws Exception {
        String productId = getTaskParam().getString(ProductTaskConstants.KEY_PRODUCT_ID);
        new GetProductInfoProcessor(mLogger, productId)
                .setProcessorCallback(new AbstractProcessor.IProcessorCallback<ProductInfo>() {
                    @Override
                    public void onSuccess(ProductInfo info) {
                        getTaskParam().put(ProductTaskConstants.KEY_PRODUCT_INFO, info);
                        notifyTaskSucceed();
                    }

                    @Override
                    public void onFailed(String error) {
                        notifyTaskFailed(ITaskResult.ERROR, error);
                    }
                })
                .process();
    }

    @Override
    public String getName() {
        return "1.获取产品信息";
    }


}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GivePriceTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.GivePriceProcessor;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 3.评估产品,给出价格
 *
 * @author xuexiang
 * @since 2/25/22 2:27 AM
 */
public class GivePriceTask extends AbstractTask {

    public GivePriceTask(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doTask() throws Exception {
        Product product = getTaskParam().getObject(ProductTaskConstants.KEY_PRODUCT, Product.class);
        new GivePriceProcessor(mLogger, product).setProcessorCallback(new AbstractProcessor.IProcessorCallback<Product>() {
            @Override
            public void onSuccess(Product result) {
                getTaskParam().put(ProductTaskConstants.KEY_PRODUCT, result);
                notifyTaskSucceed();
            }

            @Override
            public void onFailed(String error) {
                notifyTaskFailed(ITaskResult.ERROR, error);
            }
        }).process();
    }

    @Override
    public String getName() {
        return "3.评估产品,给出价格";
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/ProductTaskConstants.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

/**
 * @author xuexiang
 * @since 2/25/22 2:14 AM
 */
public final class ProductTaskConstants {

    public static final String KEY_PRODUCT_ID = "key_product_id";

    public static final String KEY_PRODUCT_INFO = "key_product_info";

    public static final String KEY_PRODUCT = "key_product";


}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/PublicProductTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.PublicProductProcessor;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 4.产品发布
 *
 * @author xuexiang
 * @since 2/25/22 2:31 AM
 */
public class PublicProductTask extends AbstractTask {

    public PublicProductTask(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doTask() throws Exception {
        Product product = getTaskParam().getObject(ProductTaskConstants.KEY_PRODUCT, Product.class);
        new PublicProductProcessor(mLogger, product).setProcessorCallback(new AbstractProcessor.IProcessorCallback<Product>() {
            @Override
            public void onSuccess(Product result) {
                getTaskParam().put(ProductTaskConstants.KEY_PRODUCT, result);
                notifyTaskSucceed();
            }

            @Override
            public void onFailed(String error) {
                notifyTaskFailed(ITaskResult.ERROR, error);
            }
        }).process();
    }

    @Override
    public String getName() {
        return "4.产品发布";
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/SearchFactoryTask.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.business.task;

import com.xuexiang.xtask.core.param.ITaskResult;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.Product;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductFactory;
import com.xuexiang.xtaskdemo.fragment.usecase.business.entity.ProductInfo;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.SearchFactoryProcessor;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 2.查找相关的工厂并生产
 *
 * @author xuexiang
 * @since 2/25/22 2:17 AM
 */
public class SearchFactoryTask extends AbstractTask {

    public SearchFactoryTask(LoggerTextView logger) {
        super(logger);
    }

    @Override
    public void doTask() throws Exception {
        ProductInfo productInfo = getTaskParam().getObject(ProductTaskConstants.KEY_PRODUCT_INFO, ProductInfo.class);
        new SearchFactoryProcessor(mLogger, productInfo)
                .setProcessorCallback(new AbstractProcessor.IProcessorCallback<ProductFactory>() {
                    @Override
                    public void onSuccess(ProductFactory factory) {
                        log("开始生产产品...");
                        Product product = factory.produce(productInfo);
                        getTaskParam().put(ProductTaskConstants.KEY_PRODUCT, product);
                        notifyTaskSucceed();
                    }

                    @Override
                    public void onFailed(String error) {
                        notifyTaskFailed(ITaskResult.ERROR, error);
                    }
                })
                .process();
    }

    @Override
    public String getName() {
        return "2.查找相关的工厂并生产";
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/BriefInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 产品简要信息
 *
 * @author xuexiang
 * @since 3/22/22 1:08 AM
 */
public class BriefInfo {

    private String id;

    protected String name;

    private String factoryId;

    private String priceId;

    private String promotionId;

    private String richId;

    public BriefInfo(String id) {
        this.id = id;
    }

    public BriefInfo(@NonNull BriefInfo briefInfo) {
        this(briefInfo.id, briefInfo.name, briefInfo.factoryId, briefInfo.priceId, briefInfo.promotionId, briefInfo.richId);
    }

    public BriefInfo(String id, String name, String factoryId, String priceId, String promotionId, String richId) {
        this.id = id;
        this.name = name;
        this.factoryId = factoryId;
        this.priceId = priceId;
        this.promotionId = promotionId;
        this.richId = richId;
    }

    public String getId() {
        return id;
    }

    public BriefInfo setId(String id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public BriefInfo setName(String name) {
        this.name = name;
        return this;
    }

    public String getFactoryId() {
        return factoryId;
    }

    public BriefInfo setFactoryId(String factoryId) {
        this.factoryId = factoryId;
        return this;
    }

    public String getPriceId() {
        return priceId;
    }

    public BriefInfo setPriceId(String priceId) {
        this.priceId = priceId;
        return this;
    }

    public String getPromotionId() {
        return promotionId;
    }

    public BriefInfo setPromotionId(String promotionId) {
        this.promotionId = promotionId;
        return this;
    }

    public String getRichId() {
        return richId;
    }

    public BriefInfo setRichId(String richId) {
        this.richId = richId;
        return this;
    }

}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/FactoryInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 工厂生产信息
 *
 * @author xuexiang
 * @since 3/22/22 1:11 AM
 */
public class FactoryInfo {

    private String id;

    /**
     * 生产地址
     */
    private String address;

    /**
     * 生产日期
     */
    private String productDate;

    /**
     * 过期日期
     */
    private String expirationDate;

    public FactoryInfo(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public FactoryInfo setId(String id) {
        this.id = id;
        return this;
    }

    public String getAddress() {
        return address;
    }

    public FactoryInfo setAddress(String address) {
        this.address = address;
        return this;
    }

    public String getProductDate() {
        return productDate;
    }

    public FactoryInfo setProductDate(String productDate) {
        this.productDate = productDate;
        return this;
    }

    public String getExpirationDate() {
        return expirationDate;
    }

    public FactoryInfo setExpirationDate(String expirationDate) {
        this.expirationDate = expirationDate;
        return this;
    }

    @NonNull
    @Override
    public String toString() {
        return "生产编号:" + id
                + ", 生产地址:" + address
                + ", 生产日期:" + productDate
                + ", 过期日期:" + expirationDate;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PriceInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 价格信息
 *
 * @author xuexiang
 * @since 3/22/22 1:10 AM
 */
public class PriceInfo {

    private String id;

    /**
     * 出厂价
     */
    private float factoryPrice;

    /**
     * 批发价
     */
    private float wholesalePrice;

    /**
     * 零售价
     */
    private float retailPrice;

    public PriceInfo(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public PriceInfo setId(String id) {
        this.id = id;
        return this;
    }

    public float getFactoryPrice() {
        return factoryPrice;
    }

    public PriceInfo setFactoryPrice(float factoryPrice) {
        this.factoryPrice = factoryPrice;
        return this;
    }

    public float getWholesalePrice() {
        return wholesalePrice;
    }

    public PriceInfo setWholesalePrice(float wholesalePrice) {
        this.wholesalePrice = wholesalePrice;
        return this;
    }

    public float getRetailPrice() {
        return retailPrice;
    }

    public PriceInfo setRetailPrice(float retailPrice) {
        this.retailPrice = retailPrice;
        return this;
    }

    @NonNull
    @Override
    public String toString() {
        return "价格编号:" + id
                + ", 出厂价:" + factoryPrice
                + ", 批发价:" + wholesalePrice
                + ", 零售价:" + retailPrice;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/Product.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 产品
 *
 * @author xuexiang
 * @since 3/22/22 1:07 AM
 */
public class Product extends BriefInfo {

    /**
     * 生产信息
     */
    private FactoryInfo factory;

    /**
     * 价格信息
     */
    private PriceInfo price;

    /**
     * 促销信息
     */
    private PromotionInfo promotion;

    /**
     * 富文本信息
     */
    private RichInfo rich;

    public Product(@NonNull BriefInfo briefInfo) {
        super(briefInfo);
    }

    public FactoryInfo getFactory() {
        return factory;
    }

    public Product setFactory(FactoryInfo factory) {
        this.factory = factory;
        return this;
    }

    public PriceInfo getPrice() {
        return price;
    }

    public Product setPrice(PriceInfo price) {
        this.price = price;
        return this;
    }

    public PromotionInfo getPromotion() {
        return promotion;
    }

    public Product setPromotion(PromotionInfo promotion) {
        this.promotion = promotion;
        return this;
    }

    public RichInfo getRich() {
        return rich;
    }

    public Product setRich(RichInfo rich) {
        this.rich = rich;
        return this;
    }

    @NonNull
    @Override
    public String toString() {
        return "产品信息: " + name
                + "\n产地信息: " + factory
                + "\n价格信息: " + price
                + "\n促销信息: " + promotion
                + "\n富文本信息: " + rich;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PromotionInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 产品促销信息
 *
 * @author xuexiang
 * @since 3/22/22 1:12 AM
 */
public class PromotionInfo {

    private String id;

    /**
     * 促销类型
     */
    private int type;

    /**
     * 促销内容
     */
    private String content;

    /**
     * 生效日期
     */
    private String effectiveDate;

    /**
     * 失效日期
     */
    private String expirationDate;

    public PromotionInfo(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public PromotionInfo setId(String id) {
        this.id = id;
        return this;
    }

    public int getType() {
        return type;
    }

    public PromotionInfo setType(int type) {
        this.type = type;
        return this;
    }

    public String getContent() {
        return content;
    }

    public PromotionInfo setContent(String content) {
        this.content = content;
        return this;
    }

    public String getEffectiveDate() {
        return effectiveDate;
    }

    public PromotionInfo setEffectiveDate(String effectiveDate) {
        this.effectiveDate = effectiveDate;
        return this;
    }

    public String getExpirationDate() {
        return expirationDate;
    }

    public PromotionInfo setExpirationDate(String expirationDate) {
        this.expirationDate = expirationDate;
        return this;
    }

    @NonNull
    @Override
    public String toString() {
        return "促销编号:" + id
                + ", 促销类型:" + type
                + ", 促销内容:" + content
                + ", 生效日期:" + effectiveDate
                + ", 失效日期:" + expirationDate;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/RichInfo.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity;

import androidx.annotation.NonNull;

/**
 * 富文本信息
 *
 * @author xuexiang
 * @since 3/22/22 1:13 AM
 */
public class RichInfo {

    private String id;

    /**
     * 描述信息
     */
    private String description;

    /**
     * 图片链接
     */
    private String imgUrl;

    /**
     * 视频链接
     */
    private String videoUrl;

    public RichInfo(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public RichInfo setId(String id) {
        this.id = id;
        return this;
    }

    public String getDescription() {
        return description;
    }

    public RichInfo setDescription(String description) {
        this.description = description;
        return this;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public RichInfo setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
        return this;
    }

    public String getVideoUrl() {
        return videoUrl;
    }

    public RichInfo setVideoUrl(String videoUrl) {
        this.videoUrl = videoUrl;
        return this;
    }

    @NonNull
    @Override
    public String toString() {
        return "富文本编号:" + id
                + ", 描述信息:" + description
                + ", 图片链接:" + imgUrl
                + ", 视频链接:" + videoUrl;
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetBriefInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.BriefInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 1 获取商品简要信息
 *
 * @author xuexiang
 * @since 3/22/22 1:18 AM
 */
public class GetBriefInfoProcessor extends AbstractProcessor<BriefInfo> {

    private String productId;

    public GetBriefInfoProcessor(LoggerTextView logger, String productId) {
        super(logger);
        this.productId = productId;
    }

    @Override
    public BriefInfo process() {
        log("[简要信息查询]开始执行...");
        BriefInfo info = getBriefInfoById(productId);
        log("[简要信息查询]执行完毕!");
        onProcessSuccess(info);
        return info;
    }

    private BriefInfo getBriefInfoById(String id) {
        // 模拟耗费的时间
        mockProcess(500);
        return new BriefInfo(id)
                .setName("统一老坛酸菜牛肉面")
                .setFactoryId("fa234632-1234-4567")
                .setPriceId("pr432359-3745-9426")
                .setPromotionId("pt235123-9654-2942")
                .setRichId("ri735294-2346-1048");
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetFactoryInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.FactoryInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 2.1 获取商品的生产信息
 *
 * @author xuexiang
 * @since 3/22/22 1:22 AM
 */
public class GetFactoryInfoProcessor extends AbstractProcessor<FactoryInfo> {

    private String factoryId;

    public GetFactoryInfoProcessor(LoggerTextView logger, String factoryId) {
        super(logger);
        this.factoryId = factoryId;
    }

    @Override
    public FactoryInfo process() {
        log("[生产信息查询]开始执行...");
        FactoryInfo info = getFactoryInfoById(factoryId);
        log("[生产信息查询]执行完毕!");
        onProcessSuccess(info);
        return info;
    }

    private FactoryInfo getFactoryInfoById(String id) {
        // 模拟耗费的时间
        mockProcess(200);
        return new FactoryInfo(id)
                .setAddress("长沙市开福区金霞经济开发区中青路1301号长沙统一企业有限公司")
                .setProductDate("2022年3月15日")
                .setExpirationDate("2030年3月15日");
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPriceInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.PriceInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 2.2 获取商品的价格信息
 *
 * @author xuexiang
 * @since 3/22/22 1:20 AM
 */
public class GetPriceInfoProcessor extends AbstractProcessor<PriceInfo> {

    private String priceId;

    public GetPriceInfoProcessor(LoggerTextView logger, String priceId) {
        super(logger);
        this.priceId = priceId;
    }

    @Override
    public PriceInfo process() {
        log("[价格信息查询]开始执行...");
        PriceInfo info = getPriceInfoById(priceId);
        log("[价格信息查询]执行完毕!");
        onProcessSuccess(info);
        return info;
    }

    private PriceInfo getPriceInfoById(String id) {
        // 模拟耗费的时间
        mockProcess(300);
        return new PriceInfo(id)
                .setFactoryPrice(1.5F)
                .setWholesalePrice(2.5F)
                .setRetailPrice(4.5F);
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPromotionInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity.PromotionInfo;
import com.xuexiang.xui.widget.textview.LoggerTextView;

/**
 * 2.3 获取商品的促销信息
 *
 * @author xuexiang
 * @since 3/22/22 1:23 AM
 */
public class GetPromotionInfoProcessor extends AbstractProcessor<PromotionInfo> {

    private String promotionId;

    public GetPromotionInfoProcessor(LoggerTextView logger, String promotionId) {
        super(logger);
        this.promotionId = promotionId;
    }

    @Override
    public PromotionInfo process() {
        log("[促销信息查询]开始执行...");
        PromotionInfo info = getPromotionInfoById(promotionId);
        log("[促销信息查询]执行完毕!");
        onProcessSuccess(info);
        return info;
    }

    private PromotionInfo getPromotionInfoById(String id) {
        // 模拟耗费的时间
        mockProcess(150);
        return new PromotionInfo(id)
                .setType(5)
                .setContent("买一送一")
                .setEffectiveDate("2022年3月15日")
                .setExpirationDate("2022年4月15日");
    }
}


================================================
FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetRichInfoProcessor.java
================================================
/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xtaskdemo.fragment.usecase.concurrent.processor;

import com.xuexiang.xtaskdemo.fragment.usecase.business.processor.AbstractProcessor;
import com.xuexiang.xtaskdemo.fragment.usecase.concurrent.entity
Download .txt
gitextract_r5lsl1_p/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .idea/
│   └── copyright/
│       ├── profiles_settings.xml
│       └── xuexiang.xml
├── JitPackUpload.gradle
├── LICENSE
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── channel
│   ├── debug.jks
│   ├── multiple-channel.gradle
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── java/
│   │   │       └── com/
│   │   │           └── xuexiang/
│   │   │               └── xtaskdemo/
│   │   │                   └── ExampleInstrumentedTest.java
│   │   ├── main/
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── xuexiang/
│   │   │   │           └── xtaskdemo/
│   │   │   │               ├── MyApp.java
│   │   │   │               ├── activity/
│   │   │   │               │   └── MainActivity.java
│   │   │   │               ├── core/
│   │   │   │               │   ├── BaseActivity.java
│   │   │   │               │   ├── BaseContainerFragment.java
│   │   │   │               │   ├── BaseFragment.java
│   │   │   │               │   ├── BaseSimpleListFragment.java
│   │   │   │               │   └── SimpleListAdapter.java
│   │   │   │               ├── fragment/
│   │   │   │               │   ├── CustomTaskFragment.java
│   │   │   │               │   ├── MainFragment.java
│   │   │   │               │   ├── TestThreadPoolFragment.java
│   │   │   │               │   ├── UseCaseFragment.java
│   │   │   │               │   ├── XTaskStepFragment.java
│   │   │   │               │   ├── XTaskThreadFragment.java
│   │   │   │               │   ├── task/
│   │   │   │               │   │   ├── Job.java
│   │   │   │               │   │   ├── JobTask.java
│   │   │   │               │   │   ├── StepATask.java
│   │   │   │               │   │   └── StepBTask.java
│   │   │   │               │   └── usecase/
│   │   │   │               │       ├── AppStartFragment.java
│   │   │   │               │       ├── ComplexBusinessFragment.java
│   │   │   │               │       ├── ConcurrentProcessFragment.java
│   │   │   │               │       ├── appstart/
│   │   │   │               │       │   ├── job/
│   │   │   │               │       │   │   ├── AbstractMockJob.java
│   │   │   │               │       │   │   ├── LongTimeJob.java
│   │   │   │               │       │   │   ├── SingleJob.java
│   │   │   │               │       │   │   └── TopPriorityJob.java
│   │   │   │               │       │   └── task/
│   │   │   │               │       │       ├── AsyncInitTask.java
│   │   │   │               │       │       └── MainInitTask.java
│   │   │   │               │       ├── business/
│   │   │   │               │       │   ├── entity/
│   │   │   │               │       │   │   ├── Product.java
│   │   │   │               │       │   │   ├── ProductFactory.java
│   │   │   │               │       │   │   └── ProductInfo.java
│   │   │   │               │       │   ├── processor/
│   │   │   │               │       │   │   ├── AbstractProcessor.java
│   │   │   │               │       │   │   ├── GetProductInfoProcessor.java
│   │   │   │               │       │   │   ├── GivePriceProcessor.java
│   │   │   │               │       │   │   ├── PublicProductProcessor.java
│   │   │   │               │       │   │   └── SearchFactoryProcessor.java
│   │   │   │               │       │   └── task/
│   │   │   │               │       │       ├── AbstractTask.java
│   │   │   │               │       │       ├── GetProductInfoTask.java
│   │   │   │               │       │       ├── GivePriceTask.java
│   │   │   │               │       │       ├── ProductTaskConstants.java
│   │   │   │               │       │       ├── PublicProductTask.java
│   │   │   │               │       │       └── SearchFactoryTask.java
│   │   │   │               │       └── concurrent/
│   │   │   │               │           ├── entity/
│   │   │   │               │           │   ├── BriefInfo.java
│   │   │   │               │           │   ├── FactoryInfo.java
│   │   │   │               │           │   ├── PriceInfo.java
│   │   │   │               │           │   ├── Product.java
│   │   │   │               │           │   ├── PromotionInfo.java
│   │   │   │               │           │   └── RichInfo.java
│   │   │   │               │           ├── processor/
│   │   │   │               │           │   ├── GetBriefInfoProcessor.java
│   │   │   │               │           │   ├── GetFactoryInfoProcessor.java
│   │   │   │               │           │   ├── GetPriceInfoProcessor.java
│   │   │   │               │           │   ├── GetPromotionInfoProcessor.java
│   │   │   │               │           │   └── GetRichInfoProcessor.java
│   │   │   │               │           └── task/
│   │   │   │               │               ├── GetBriefInfoTask.java
│   │   │   │               │               ├── GetFactoryInfoTask.java
│   │   │   │               │               ├── GetPriceInfoTask.java
│   │   │   │               │               ├── GetPromotionInfoTask.java
│   │   │   │               │               └── GetRichInfoTask.java
│   │   │   │               └── utils/
│   │   │   │                   ├── XToastUtils.java
│   │   │   │                   ├── sdkinit/
│   │   │   │                   │   ├── UMengInit.java
│   │   │   │                   │   └── XBasicLibInit.java
│   │   │   │                   └── service/
│   │   │   │                       └── JsonSerializationService.java
│   │   │   └── res/
│   │   │       ├── drawable/
│   │   │       │   └── ic_launcher_background.xml
│   │   │       ├── drawable-v24/
│   │   │       │   └── ic_launcher_foreground.xml
│   │   │       ├── layout/
│   │   │       │   ├── adapter_item_simple_list_2.xml
│   │   │       │   ├── fragment_usecase_compare.xml
│   │   │       │   └── fragment_usecase_template.xml
│   │   │       ├── mipmap-anydpi-v26/
│   │   │       │   ├── ic_launcher.xml
│   │   │       │   └── ic_launcher_round.xml
│   │   │       └── values/
│   │   │           ├── colors.xml
│   │   │           ├── strings.xml
│   │   │           ├── styles.xml
│   │   │           └── styles_widget.xml
│   │   └── test/
│   │       └── java/
│   │           └── com/
│   │               └── xuexiang/
│   │                   └── xtaskdemo/
│   │                       └── ExampleUnitTest.java
│   └── x-library-simple.gradle
├── art/
│   └── xtask.mdj
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── versions.gradle
├── xtask-core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── xuexiang/
│                       └── xtask/
│                           ├── XTask.java
│                           ├── api/
│                           │   ├── TaskChainEngine.java
│                           │   └── step/
│                           │       ├── ConcurrentGroupTaskStep.java
│                           │       ├── SerialGroupTaskStep.java
│                           │       ├── SimpleTaskStep.java
│                           │       └── XTaskStep.java
│                           ├── core/
│                           │   ├── ITaskChainCallback.java
│                           │   ├── ITaskChainEngine.java
│                           │   ├── ThreadType.java
│                           │   ├── param/
│                           │   │   ├── IDataStore.java
│                           │   │   ├── ITaskParam.java
│                           │   │   ├── ITaskResult.java
│                           │   │   └── impl/
│                           │   │       ├── MapDataStore.java
│                           │   │       ├── TaskParam.java
│                           │   │       └── TaskResult.java
│                           │   └── step/
│                           │       ├── IGroupTaskStep.java
│                           │       ├── ITaskStep.java
│                           │       ├── ITaskStepController.java
│                           │       ├── ITaskStepHandler.java
│                           │       ├── ITaskStepLifecycle.java
│                           │       └── impl/
│                           │           ├── AbstractGroupTaskStep.java
│                           │           ├── AbstractTaskStep.java
│                           │           ├── AutoDestroyTaskChainCallback.java
│                           │           ├── AutoNotifyTaskStepHandler.java
│                           │           ├── TaskChainCallbackAdapter.java
│                           │           └── TaskCommand.java
│                           └── utils/
│                               ├── CancellerPoolUtils.java
│                               ├── CommonUtils.java
│                               └── TaskUtils.java
└── xtask-thread/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    └── src/
        └── main/
            ├── AndroidManifest.xml
            └── java/
                └── com/
                    └── xuexiang/
                        └── xtask/
                            ├── logger/
                            │   ├── ILogger.java
                            │   ├── LogcatLogger.java
                            │   └── TaskLogger.java
                            └── thread/
                                ├── XTaskExecutor.java
                                ├── executor/
                                │   ├── ICategoryExecutorCore.java
                                │   ├── IExecutorCore.java
                                │   ├── IPriorityExecutorCore.java
                                │   ├── IScheduledExecutorCore.java
                                │   └── impl/
                                │       ├── CategoryExecutorCore.java
                                │       ├── PriorityExecutorCore.java
                                │       └── ScheduledExecutorCore.java
                                ├── pool/
                                │   ├── DefaultScheduledThreadPoolExecutor.java
                                │   ├── DefaultThreadPoolExecutor.java
                                │   ├── PriorityThreadPoolExecutor.java
                                │   ├── TaskRecordPolicy.java
                                │   ├── TaskThreadFactory.java
                                │   ├── base/
                                │   │   ├── BaseScheduledThreadPoolExecutor.java
                                │   │   └── BaseThreadPoolExecutor.java
                                │   └── cancel/
                                │       ├── CancelHandlerRunnable.java
                                │       ├── ICancelable.java
                                │       ├── ICanceller.java
                                │       ├── ICancellerPool.java
                                │       ├── IFuture.java
                                │       ├── IScheduledFuture.java
                                │       └── TaskCancellerPool.java
                                ├── priority/
                                │   ├── IPriority.java
                                │   ├── IPriorityCallable.java
                                │   ├── IPriorityComparable.java
                                │   ├── IPriorityFuture.java
                                │   ├── IPriorityRunnable.java
                                │   ├── IPriorityStrategy.java
                                │   └── impl/
                                │       ├── DefaultPriorityCallable.java
                                │       ├── DefaultPriorityFuture.java
                                │       ├── DefaultPriorityRunnable.java
                                │       ├── DefaultPriorityStrategy.java
                                │       └── Priority.java
                                └── utils/
                                    ├── CancelUtils.java
                                    ├── ExecutorUtils.java
                                    └── PriorityUtils.java
Download .txt
SYMBOL INDEX (1086 symbols across 130 files)

FILE: app/src/androidTest/java/com/xuexiang/xtaskdemo/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 18) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 20) | @Test

FILE: app/src/main/java/com/xuexiang/xtaskdemo/MyApp.java
  class MyApp (line 33) | public class MyApp extends Application {
    method attachBaseContext (line 35) | @Override
    method onCreate (line 42) | @Override
    method initLibs (line 56) | private void initLibs() {
    method isDebug (line 65) | public static boolean isDebug() {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/activity/MainActivity.java
  class MainActivity (line 31) | public class MainActivity extends BaseActivity {
    method onCreate (line 33) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseActivity.java
  class BaseActivity (line 39) | public class BaseActivity extends XPageActivity {
    method attachBaseContext (line 43) | @Override
    method onCreate (line 49) | @Override
    method initStatusBarStyle (line 59) | protected void initStatusBarStyle() {
    method openPage (line 70) | public <T extends XPageFragment> T openPage(Class<T> clazz, boolean ad...
    method openNewPage (line 81) | public <T extends XPageFragment> T openNewPage(Class<T> clazz) {
    method switchPage (line 93) | public <T extends XPageFragment> T switchPage(Class<T> clazz) {
    method serializeObject (line 103) | public String serializeObject(Object object) {
    method onRelease (line 107) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseContainerFragment.java
  class BaseContainerFragment (line 45) | public abstract class BaseContainerFragment extends XPageContainerListFr...
    method initPage (line 47) | @Override
    method initTitle (line 54) | protected TitleBar initTitle() {
    method initData (line 63) | @Override
    method onItemClick (line 85) | @Override
    method onItemClick (line 90) | @SingleClick
    method onDestroyView (line 95) | @Override
    method onConfigurationChanged (line 101) | @Override
    method onResume (line 112) | @Override
    method onPause (line 118) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseFragment.java
  class BaseFragment (line 49) | public abstract class BaseFragment extends XPageFragment {
    method initPage (line 53) | @Override
    method initTitle (line 60) | protected TitleBar initTitle() {
    method initListeners (line 64) | @Override
    method getMessageLoader (line 69) | public IMessageLoader getMessageLoader() {
    method getMessageLoader (line 76) | public IMessageLoader getMessageLoader(String message) {
    method onConfigurationChanged (line 85) | @Override
    method onResume (line 96) | @Override
    method onPause (line 102) | @Override
    method openNewPage (line 118) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
    method openNewPage (line 131) | public <T extends XPageFragment> Fragment openNewPage(String pageName) {
    method openNewPage (line 147) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, ...
    method openNewPage (line 163) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, ...
    method openPage (line 168) | public Fragment openPage(PageOption option, String key, Object value) {
    method openPage (line 201) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boo...
    method openPage (line 217) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, Str...
    method openPage (line 231) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boo...
    method openPage (line 245) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, Str...
    method openPageForResult (line 261) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method openPageForResult (line 276) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method openPageForResult (line 291) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method serializeObject (line 303) | public String serializeObject(Object object) {
    method deserializeObject (line 314) | public <T> T deserializeObject(String input, Type clazz) {
    method hideCurrentPageSoftInput (line 318) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/BaseSimpleListFragment.java
  class BaseSimpleListFragment (line 45) | public abstract class BaseSimpleListFragment extends XPageSimpleListFrag...
    method initPage (line 47) | @Override
    method initTitle (line 54) | protected TitleBar initTitle() {
    method onConfigurationChanged (line 63) | @Override
    method onResume (line 74) | @Override
    method onPause (line 80) | @Override
    method openNewPage (line 95) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
    method openNewPage (line 108) | public <T extends XPageFragment> Fragment openNewPage(String pageName) {
    method openNewPage (line 124) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, ...
    method openNewPage (line 140) | public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, ...
    method openPage (line 145) | public Fragment openPage(PageOption option, String key, Object value) {
    method openPage (line 178) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boo...
    method openPage (line 194) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, Str...
    method openPage (line 208) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boo...
    method openPage (line 222) | public <T extends XPageFragment> Fragment openPage(Class<T> clazz, Str...
    method openPageForResult (line 238) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method openPageForResult (line 253) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method openPageForResult (line 268) | public <T extends XPageFragment> Fragment openPageForResult(Class<T> c...
    method serializeObject (line 280) | public String serializeObject(Object object) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/core/SimpleListAdapter.java
  class SimpleListAdapter (line 37) | public class SimpleListAdapter extends BaseListAdapter<Map<String, Strin...
    method SimpleListAdapter (line 42) | public SimpleListAdapter(Context context, List<Map<String, String>> da...
    method newViewHolder (line 46) | @Override
    method getLayoutId (line 54) | @Override
    method convert (line 59) | @Override
    class ViewHolder (line 70) | public static class ViewHolder {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/CustomTaskFragment.java
  class CustomTaskFragment (line 50) | @Page(name = "自定义任务使用\n通过继承SimpleTaskStep/AbstractTaskStep实现")
    method initSimpleData (line 57) | @Override
    method onItemClick (line 65) | @Override
    method doSimpleTaskStep (line 85) | private void doSimpleTaskStep() {
    method doSimpleAbstractTaskStep (line 135) | private void doSimpleAbstractTaskStep() {
    method doComplexTaskStep (line 152) | private void doComplexTaskStep() {
    method addCanceller (line 168) | private void addCanceller(ICanceller canceller) {
    method onDestroyView (line 174) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/MainFragment.java
  class MainFragment (line 36) | @Page(name = "XTask", anim = CoreAnim.none)
    method getPagesClasses (line 39) | @Override
    method initTitle (line 51) | @Override
    method onKeyDown (line 60) | @Override
    method onRetry (line 68) | @Override
    method onExit (line 73) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/TestThreadPoolFragment.java
  class TestThreadPoolFragment (line 41) | @Page(name = "线程池测试页面")
    method initSimpleData (line 46) | @Override
    method onItemClick (line 55) | @Override
    method getRunnable (line 132) | private static Runnable getRunnable(final String name) {
    method getPriority (line 159) | private static Integer getPriority(Object o) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/UseCaseFragment.java
  class UseCaseFragment (line 30) | @Page(name = "应用场景\n列举常用的使用案例")
    method getPagesClasses (line 33) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskStepFragment.java
  class XTaskStepFragment (line 53) | @Page(name = "XTaskStep任务使用\n通过XTaskStep进行简化使用")
    method initSimpleData (line 60) | @Override
    method onItemClick (line 72) | @Override
    method doSimpleTaskChain (line 105) | private void doSimpleTaskChain() {
    method doParamTaskChain (line 139) | private void doParamTaskChain() {
    method doThreadTypeTaskChain (line 178) | private void doThreadTypeTaskChain() {
    method doSerialGroupTaskChain (line 203) | private void doSerialGroupTaskChain() {
    method doConcurrentGroupTaskChain (line 228) | private void doConcurrentGroupTaskChain() {
    method doTaskFailed (line 254) | private void doTaskFailed() {
    method doTaskException (line 288) | private void doTaskException() {
    method addCanceller (line 320) | private void addCanceller(ICanceller canceller) {
    class SimpleTaskCommand (line 326) | private static class SimpleTaskCommand extends TaskCommand {
      method SimpleTaskCommand (line 330) | private SimpleTaskCommand(long during) {
      method run (line 334) | @Override
    method onDestroyView (line 346) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskThreadFragment.java
  class XTaskThreadFragment (line 38) | @Page(name = "XTask线程池使用\nXTask拥有丰富的线程调度方法")
    method initSimpleData (line 45) | @Override
    method onItemClick (line 58) | @Override
    method doNormalAsync (line 90) | private void doNormalAsync() {
    method doEmergentAsync (line 99) | private void doEmergentAsync() {
    method doBackgroundAsync (line 108) | private void doBackgroundAsync() {
    method doPriorityAsync (line 117) | private void doPriorityAsync() {
    method doDelayOnMainThread (line 126) | private void doDelayOnMainThread() {
    method doDelay (line 134) | private void doDelay() {
    method doPollingFixedRate (line 143) | private void doPollingFixedRate() {
    method doPollingFixedDelay (line 152) | private void doPollingFixedDelay() {
    method mockProcess (line 166) | public void mockProcess(long time) {
    method onDestroyView (line 174) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/Job.java
  class Job (line 35) | public class Job implements Runnable {
    method Job (line 41) | public Job(@NonNull ITaskStepController controller) {
    method run (line 45) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/JobTask.java
  class JobTask (line 30) | public class JobTask extends SimpleTaskStep {
    method JobTask (line 37) | public JobTask() {
    method doTask (line 42) | @Override
    method isAutoNotify (line 47) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepATask.java
  class StepATask (line 32) | public class StepATask extends AbstractTaskStep {
    method doTask (line 36) | @Override
    method getName (line 45) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepBTask.java
  class StepBTask (line 32) | public class StepBTask extends AbstractTaskStep {
    method doTask (line 34) | @Override
    method getName (line 45) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/AppStartFragment.java
  class AppStartFragment (line 58) | @Page(name = "应用冷启动优化")
    method getLayoutId (line 64) | @Override
    method initViews (line 69) | @Override
    method onViewClicked (line 75) | @SingleClick
    method doJobBeforeImprove (line 97) | private void doJobBeforeImprove(long startTime) {
    method doJobAfterImprove (line 109) | private void doJobAfterImprove(final long startTime) {
    method log (line 133) | public void log(String logContent) {
    method clearLog (line 139) | public void clearLog() {
    method onDestroyView (line 145) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ComplexBusinessFragment.java
  class ComplexBusinessFragment (line 66) | @Page(name = "复杂业务流程处理")
    method getLayoutId (line 76) | @Override
    method initViews (line 81) | @Override
    method onViewClicked (line 86) | @SingleClick
    method doBusinessNormal (line 112) | private void doBusinessNormal(final long startTime) {
    method doBusinessRxJava (line 153) | private void doBusinessRxJava(final long startTime) {
    method doBusinessXTask (line 182) | private void doBusinessXTask(final long startTime) {
    method log (line 204) | public void log(String logContent) {
    method clearLog (line 210) | public void clearLog() {
    method onDestroyView (line 216) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ConcurrentProcessFragment.java
  class ConcurrentProcessFragment (line 80) | @Page(name = "复杂并发任务处理")
    method getLayoutId (line 90) | @Override
    method initViews (line 96) | @Override
    method onViewClicked (line 101) | @SingleClick
    method queryInfoNormal (line 126) | private void queryInfoNormal(final long startTime, String productId) {
    method queryInfoRxJava (line 189) | private void queryInfoRxJava(final long startTime, String productId) {
    method queryInfoXTask (line 220) | private void queryInfoXTask(final long startTime, String productId) {
    method log (line 245) | public void log(String logContent) {
    method clearLog (line 251) | public void clearLog() {
    method onDestroyView (line 257) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/AbstractMockJob.java
  class AbstractMockJob (line 28) | public abstract class AbstractMockJob {
    method AbstractMockJob (line 32) | public AbstractMockJob(LoggerTextView logger) {
    method doJob (line 39) | public abstract void doJob();
    method log (line 41) | public void log(String logContent) {
    method mockProcess (line 53) | public void mockProcess(long time) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/LongTimeJob.java
  class LongTimeJob (line 28) | public class LongTimeJob extends AbstractMockJob {
    method LongTimeJob (line 30) | public LongTimeJob(LoggerTextView logger) {
    method doJob (line 34) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/SingleJob.java
  class SingleJob (line 28) | public class SingleJob extends AbstractMockJob {
    method SingleJob (line 32) | public SingleJob(int index, LoggerTextView logger) {
    method doJob (line 37) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/TopPriorityJob.java
  class TopPriorityJob (line 28) | public class TopPriorityJob extends AbstractMockJob {
    method TopPriorityJob (line 30) | public TopPriorityJob(LoggerTextView logger) {
    method doJob (line 34) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/AsyncInitTask.java
  class AsyncInitTask (line 34) | public class AsyncInitTask extends SimpleTaskStep {
    method AsyncInitTask (line 38) | public AsyncInitTask(LoggerTextView logger) {
    method doTask (line 42) | @Override
    method getName (line 48) | @Override
    method getThreadType (line 53) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/MainInitTask.java
  class MainInitTask (line 33) | public class MainInitTask extends SimpleTaskStep {
    method MainInitTask (line 37) | public MainInitTask(LoggerTextView logger) {
    method doTask (line 41) | @Override
    method getName (line 48) | @Override
    method getThreadType (line 53) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/Product.java
  class Product (line 26) | public class Product {
    method Product (line 36) | public Product(ProductInfo info, String address) {
    method getInfo (line 41) | public ProductInfo getInfo() {
    method setInfo (line 45) | public Product setInfo(ProductInfo info) {
    method getAddress (line 50) | public String getAddress() {
    method setAddress (line 54) | public Product setAddress(String address) {
    method getPrice (line 59) | public String getPrice() {
    method setPrice (line 63) | public Product setPrice(String price) {
    method getPublicTime (line 68) | public String getPublicTime() {
    method setPublicTime (line 73) | public Product setPublicTime(String publicTime) {
    method toString (line 78) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductFactory.java
  class ProductFactory (line 26) | public class ProductFactory {
    method ProductFactory (line 32) | public ProductFactory(String id, String address) {
    method produce (line 37) | public Product produce(ProductInfo info) {
    method getId (line 41) | public String getId() {
    method setId (line 45) | public ProductFactory setId(String id) {
    method getAddress (line 50) | public String getAddress() {
    method setAddress (line 54) | public ProductFactory setAddress(String address) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductInfo.java
  class ProductInfo (line 26) | public class ProductInfo {
    method ProductInfo (line 40) | public ProductInfo(String id) {
    method ProductInfo (line 44) | public ProductInfo(String id, String brand, String quality) {
    method getId (line 50) | public String getId() {
    method setId (line 54) | public ProductInfo setId(String id) {
    method getBrand (line 59) | public String getBrand() {
    method setBrand (line 63) | public ProductInfo setBrand(String brand) {
    method getQuality (line 68) | public String getQuality() {
    method setQuality (line 72) | public ProductInfo setQuality(String quality) {
    method toString (line 77) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/AbstractProcessor.java
  class AbstractProcessor (line 28) | public abstract class AbstractProcessor<T> {
    method AbstractProcessor (line 35) | public AbstractProcessor(LoggerTextView logger) {
    method setProcessorCallback (line 39) | public AbstractProcessor setProcessorCallback(IProcessorCallback<T> ca...
    method process (line 49) | public abstract T process();
    method log (line 51) | public void log(String logContent) {
    method onProcessSuccess (line 57) | public void onProcessSuccess(T t) {
    method onProcessFailed (line 63) | public void onProcessFailed(String error) {
    method mockProcess (line 74) | public void mockProcess(long time) {
    class ProcessorCallbackAdapter (line 82) | public abstract static class ProcessorCallbackAdapter<T> implements IP...
      method onFailed (line 83) | @Override
    type IProcessorCallback (line 89) | public interface IProcessorCallback<T> {
      method onSuccess (line 95) | void onSuccess(T result);
      method onFailed (line 102) | void onFailed(String error);

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GetProductInfoProcessor.java
  class GetProductInfoProcessor (line 29) | public class GetProductInfoProcessor extends AbstractProcessor<ProductIn...
    method GetProductInfoProcessor (line 33) | public GetProductInfoProcessor(LoggerTextView logger, String id) {
    method process (line 38) | @Override
    method getProductInfoById (line 47) | private ProductInfo getProductInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GivePriceProcessor.java
  class GivePriceProcessor (line 28) | public class GivePriceProcessor extends AbstractProcessor<Product> {
    method GivePriceProcessor (line 32) | public GivePriceProcessor(LoggerTextView logger, Product product) {
    method process (line 37) | @Override
    method givePrice (line 47) | private String givePrice(Product product) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/PublicProductProcessor.java
  class PublicProductProcessor (line 30) | public class PublicProductProcessor extends AbstractProcessor<Product> {
    method PublicProductProcessor (line 34) | public PublicProductProcessor(LoggerTextView logger, Product product) {
    method PublicProductProcessor (line 39) | public PublicProductProcessor(LoggerTextView logger) {
    method process (line 43) | @Override
    method getPublicPlan (line 53) | private String getPublicPlan(Product product) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/SearchFactoryProcessor.java
  class SearchFactoryProcessor (line 30) | public class SearchFactoryProcessor extends AbstractProcessor<ProductFac...
    method SearchFactoryProcessor (line 34) | public SearchFactoryProcessor(LoggerTextView logger, ProductInfo info) {
    method process (line 39) | @Override
    method searchFactoryByBrand (line 48) | private ProductFactory searchFactoryByBrand(String brand) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/AbstractTask.java
  class AbstractTask (line 29) | public abstract class AbstractTask extends SimpleTaskStep {
    method AbstractTask (line 33) | public AbstractTask(LoggerTextView logger) {
    method log (line 37) | public void log(String logContent) {
    method isAutoNotify (line 43) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GetProductInfoTask.java
  class GetProductInfoTask (line 32) | public class GetProductInfoTask extends AbstractTask {
    method GetProductInfoTask (line 34) | public GetProductInfoTask(LoggerTextView logger) {
    method doTask (line 38) | @Override
    method getName (line 57) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GivePriceTask.java
  class GivePriceTask (line 32) | public class GivePriceTask extends AbstractTask {
    method GivePriceTask (line 34) | public GivePriceTask(LoggerTextView logger) {
    method doTask (line 38) | @Override
    method getName (line 55) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/ProductTaskConstants.java
  class ProductTaskConstants (line 24) | public final class ProductTaskConstants {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/PublicProductTask.java
  class PublicProductTask (line 32) | public class PublicProductTask extends AbstractTask {
    method PublicProductTask (line 34) | public PublicProductTask(LoggerTextView logger) {
    method doTask (line 38) | @Override
    method getName (line 55) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/SearchFactoryTask.java
  class SearchFactoryTask (line 34) | public class SearchFactoryTask extends AbstractTask {
    method SearchFactoryTask (line 36) | public SearchFactoryTask(LoggerTextView logger) {
    method doTask (line 40) | @Override
    method getName (line 61) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/BriefInfo.java
  class BriefInfo (line 28) | public class BriefInfo {
    method BriefInfo (line 42) | public BriefInfo(String id) {
    method BriefInfo (line 46) | public BriefInfo(@NonNull BriefInfo briefInfo) {
    method BriefInfo (line 50) | public BriefInfo(String id, String name, String factoryId, String pric...
    method getId (line 59) | public String getId() {
    method setId (line 63) | public BriefInfo setId(String id) {
    method getName (line 68) | public String getName() {
    method setName (line 72) | public BriefInfo setName(String name) {
    method getFactoryId (line 77) | public String getFactoryId() {
    method setFactoryId (line 81) | public BriefInfo setFactoryId(String factoryId) {
    method getPriceId (line 86) | public String getPriceId() {
    method setPriceId (line 90) | public BriefInfo setPriceId(String priceId) {
    method getPromotionId (line 95) | public String getPromotionId() {
    method setPromotionId (line 99) | public BriefInfo setPromotionId(String promotionId) {
    method getRichId (line 104) | public String getRichId() {
    method setRichId (line 108) | public BriefInfo setRichId(String richId) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/FactoryInfo.java
  class FactoryInfo (line 28) | public class FactoryInfo {
    method FactoryInfo (line 47) | public FactoryInfo(String id) {
    method getId (line 51) | public String getId() {
    method setId (line 55) | public FactoryInfo setId(String id) {
    method getAddress (line 60) | public String getAddress() {
    method setAddress (line 64) | public FactoryInfo setAddress(String address) {
    method getProductDate (line 69) | public String getProductDate() {
    method setProductDate (line 73) | public FactoryInfo setProductDate(String productDate) {
    method getExpirationDate (line 78) | public String getExpirationDate() {
    method setExpirationDate (line 82) | public FactoryInfo setExpirationDate(String expirationDate) {
    method toString (line 87) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PriceInfo.java
  class PriceInfo (line 28) | public class PriceInfo {
    method PriceInfo (line 47) | public PriceInfo(String id) {
    method getId (line 51) | public String getId() {
    method setId (line 55) | public PriceInfo setId(String id) {
    method getFactoryPrice (line 60) | public float getFactoryPrice() {
    method setFactoryPrice (line 64) | public PriceInfo setFactoryPrice(float factoryPrice) {
    method getWholesalePrice (line 69) | public float getWholesalePrice() {
    method setWholesalePrice (line 73) | public PriceInfo setWholesalePrice(float wholesalePrice) {
    method getRetailPrice (line 78) | public float getRetailPrice() {
    method setRetailPrice (line 82) | public PriceInfo setRetailPrice(float retailPrice) {
    method toString (line 87) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/Product.java
  class Product (line 28) | public class Product extends BriefInfo {
    method Product (line 50) | public Product(@NonNull BriefInfo briefInfo) {
    method getFactory (line 54) | public FactoryInfo getFactory() {
    method setFactory (line 58) | public Product setFactory(FactoryInfo factory) {
    method getPrice (line 63) | public PriceInfo getPrice() {
    method setPrice (line 67) | public Product setPrice(PriceInfo price) {
    method getPromotion (line 72) | public PromotionInfo getPromotion() {
    method setPromotion (line 76) | public Product setPromotion(PromotionInfo promotion) {
    method getRich (line 81) | public RichInfo getRich() {
    method setRich (line 85) | public Product setRich(RichInfo rich) {
    method toString (line 90) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PromotionInfo.java
  class PromotionInfo (line 28) | public class PromotionInfo {
    method PromotionInfo (line 52) | public PromotionInfo(String id) {
    method getId (line 56) | public String getId() {
    method setId (line 60) | public PromotionInfo setId(String id) {
    method getType (line 65) | public int getType() {
    method setType (line 69) | public PromotionInfo setType(int type) {
    method getContent (line 74) | public String getContent() {
    method setContent (line 78) | public PromotionInfo setContent(String content) {
    method getEffectiveDate (line 83) | public String getEffectiveDate() {
    method setEffectiveDate (line 87) | public PromotionInfo setEffectiveDate(String effectiveDate) {
    method getExpirationDate (line 92) | public String getExpirationDate() {
    method setExpirationDate (line 96) | public PromotionInfo setExpirationDate(String expirationDate) {
    method toString (line 101) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/RichInfo.java
  class RichInfo (line 28) | public class RichInfo {
    method RichInfo (line 47) | public RichInfo(String id) {
    method getId (line 51) | public String getId() {
    method setId (line 55) | public RichInfo setId(String id) {
    method getDescription (line 60) | public String getDescription() {
    method setDescription (line 64) | public RichInfo setDescription(String description) {
    method getImgUrl (line 69) | public String getImgUrl() {
    method setImgUrl (line 73) | public RichInfo setImgUrl(String imgUrl) {
    method getVideoUrl (line 78) | public String getVideoUrl() {
    method setVideoUrl (line 82) | public RichInfo setVideoUrl(String videoUrl) {
    method toString (line 87) | @NonNull

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetBriefInfoProcessor.java
  class GetBriefInfoProcessor (line 30) | public class GetBriefInfoProcessor extends AbstractProcessor<BriefInfo> {
    method GetBriefInfoProcessor (line 34) | public GetBriefInfoProcessor(LoggerTextView logger, String productId) {
    method process (line 39) | @Override
    method getBriefInfoById (line 48) | private BriefInfo getBriefInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetFactoryInfoProcessor.java
  class GetFactoryInfoProcessor (line 30) | public class GetFactoryInfoProcessor extends AbstractProcessor<FactoryIn...
    method GetFactoryInfoProcessor (line 34) | public GetFactoryInfoProcessor(LoggerTextView logger, String factoryId) {
    method process (line 39) | @Override
    method getFactoryInfoById (line 48) | private FactoryInfo getFactoryInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPriceInfoProcessor.java
  class GetPriceInfoProcessor (line 30) | public class GetPriceInfoProcessor extends AbstractProcessor<PriceInfo> {
    method GetPriceInfoProcessor (line 34) | public GetPriceInfoProcessor(LoggerTextView logger, String priceId) {
    method process (line 39) | @Override
    method getPriceInfoById (line 48) | private PriceInfo getPriceInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPromotionInfoProcessor.java
  class GetPromotionInfoProcessor (line 30) | public class GetPromotionInfoProcessor extends AbstractProcessor<Promoti...
    method GetPromotionInfoProcessor (line 34) | public GetPromotionInfoProcessor(LoggerTextView logger, String promoti...
    method process (line 39) | @Override
    method getPromotionInfoById (line 48) | private PromotionInfo getPromotionInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetRichInfoProcessor.java
  class GetRichInfoProcessor (line 30) | public class GetRichInfoProcessor extends AbstractProcessor<RichInfo> {
    method GetRichInfoProcessor (line 33) | public GetRichInfoProcessor(LoggerTextView logger, String richId) {
    method process (line 38) | @Override
    method getRichInfoById (line 47) | private RichInfo getRichInfoById(String id) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetBriefInfoTask.java
  class GetBriefInfoTask (line 35) | public class GetBriefInfoTask extends AbstractTask {
    method GetBriefInfoTask (line 37) | public GetBriefInfoTask(LoggerTextView logger) {
    method doTask (line 41) | @Override
    method getName (line 61) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetFactoryInfoTask.java
  class GetFactoryInfoTask (line 36) | public class GetFactoryInfoTask extends AbstractTask {
    method GetFactoryInfoTask (line 38) | public GetFactoryInfoTask(LoggerTextView logger) {
    method doTask (line 42) | @Override
    method getName (line 66) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetPriceInfoTask.java
  class GetPriceInfoTask (line 36) | public class GetPriceInfoTask extends AbstractTask {
    method GetPriceInfoTask (line 38) | public GetPriceInfoTask(LoggerTextView logger) {
    method doTask (line 42) | @Override
    method getName (line 66) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetPromotionInfoTask.java
  class GetPromotionInfoTask (line 36) | public class GetPromotionInfoTask extends AbstractTask {
    method GetPromotionInfoTask (line 38) | public GetPromotionInfoTask(LoggerTextView logger) {
    method doTask (line 42) | @Override
    method getName (line 66) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetRichInfoTask.java
  class GetRichInfoTask (line 36) | public class GetRichInfoTask extends AbstractTask {
    method GetRichInfoTask (line 38) | public GetRichInfoTask(LoggerTextView logger) {
    method doTask (line 42) | @Override
    method getName (line 66) | @Override

FILE: app/src/main/java/com/xuexiang/xtaskdemo/utils/XToastUtils.java
  class XToastUtils (line 33) | public final class XToastUtils {
    method XToastUtils (line 36) | private XToastUtils() {
    method toast (line 48) | @MainThread
    method toast (line 53) | @MainThread
    method toast (line 58) | @MainThread
    method toast (line 63) | @MainThread
    method error (line 70) | @MainThread
    method error (line 75) | @MainThread
    method error (line 80) | @MainThread
    method error (line 85) | @MainThread
    method success (line 92) | @MainThread
    method success (line 97) | @MainThread
    method success (line 102) | @MainThread
    method success (line 107) | @MainThread
    method info (line 114) | @MainThread
    method info (line 119) | @MainThread
    method info (line 124) | @MainThread
    method info (line 129) | @MainThread
    method warning (line 136) | @MainThread
    method warning (line 141) | @MainThread
    method warning (line 146) | @MainThread
    method warning (line 151) | @MainThread

FILE: app/src/main/java/com/xuexiang/xtaskdemo/utils/sdkinit/UMengInit.java
  class UMengInit (line 37) | public final class UMengInit {
    method UMengInit (line 39) | private UMengInit() {
    method init (line 48) | public static void init(@NonNull Context context) {
    method init (line 58) | public static void init(Application application) {
    method isAgreePrivacy (line 74) | private static boolean isAgreePrivacy() {
    method realInit (line 82) | private static void realInit(Application application) {
    method getChannel (line 100) | private static String getChannel(final Context context) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/utils/sdkinit/XBasicLibInit.java
  class XBasicLibInit (line 38) | public final class XBasicLibInit {
    method XBasicLibInit (line 40) | private XBasicLibInit() {
    method init (line 47) | public static void init(Application application) {
    method initXUtil (line 67) | private static void initXUtil(Application application) {
    method initXPage (line 75) | private static void initXPage(Application application) {
    method initXAOP (line 85) | private static void initXAOP(Application application) {
    method initXUI (line 95) | private static void initXUI(Application application) {
    method initRouter (line 103) | private static void initRouter(Application application) {

FILE: app/src/main/java/com/xuexiang/xtaskdemo/utils/service/JsonSerializationService.java
  class JsonSerializationService (line 32) | @Router(path = "/service/json")
    method object2Json (line 40) | @Override
    method parseObject (line 52) | @Override
    method init (line 62) | @Override

FILE: app/src/test/java/com/xuexiang/xtaskdemo/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test

FILE: xtask-core/src/main/java/com/xuexiang/xtask/XTask.java
  class XTask (line 48) | public final class XTask {
    method debug (line 57) | public static void debug(boolean isDebug) {
    method debug (line 66) | public static void debug(String tag) {
    method setLogger (line 75) | public static void setLogger(@NonNull ILogger logger) {
    method setIsLogThreadName (line 84) | public static void setIsLogThreadName(boolean isLogThreadName) {
    method getTaskChain (line 95) | public static TaskChainEngine getTaskChain() {
    method getTaskChain (line 105) | public static TaskChainEngine getTaskChain(String name) {
    method getTask (line 117) | public static XTaskStep getTask(@NonNull TaskCommand command) {
    method getTask (line 128) | public static XTaskStep getTask(@NonNull TaskCommand command, boolean ...
    method getTask (line 139) | public static XTaskStep getTask(@NonNull TaskCommand command, ThreadTy...
    method getTask (line 150) | public static XTaskStep getTask(@NonNull TaskCommand command, @NonNull...
    method getTask (line 162) | public static XTaskStep getTask(@NonNull TaskCommand command, ThreadTy...
    method getTaskBuilder (line 172) | public static XTaskStep.Builder getTaskBuilder(@NonNull TaskCommand co...
    method getConcurrentGroupTask (line 183) | public static ConcurrentGroupTaskStep getConcurrentGroupTask() {
    method getConcurrentGroupTask (line 193) | public static ConcurrentGroupTaskStep getConcurrentGroupTask(@NonNull ...
    method getConcurrentGroupTask (line 203) | public static ConcurrentGroupTaskStep getConcurrentGroupTask(@NonNull ...
    method getSerialGroupTask (line 214) | public static SerialGroupTaskStep getSerialGroupTask() {
    method getSerialGroupTask (line 224) | public static SerialGroupTaskStep getSerialGroupTask(@NonNull String n...
    method getSerialGroupTask (line 234) | public static SerialGroupTaskStep getSerialGroupTask(@NonNull ThreadTy...
    method setCancellerPool (line 245) | public static void setCancellerPool(ICancellerPool cancellerPool) {
    method cancelTaskChain (line 255) | public static boolean cancelTaskChain(String name) {
    method cancelTaskChain (line 264) | public static void cancelTaskChain(String... names) {
    method cancelTaskChain (line 274) | public static void cancelTaskChain(Collection<String> names) {
    method cancelAllTaskChain (line 281) | public static void cancelAllTaskChain() {
    method clearTaskChain (line 290) | public static void clearTaskChain(boolean ifNeedCancel) {
    method setPriorityExecutorCore (line 301) | public static void setPriorityExecutorCore(@NonNull IPriorityExecutorC...
    method setCategoryExecutorCore (line 310) | public static void setCategoryExecutorCore(@NonNull ICategoryExecutorC...
    method setScheduledExecutorCore (line 319) | public static void setScheduledExecutorCore(@NonNull IScheduledExecuto...
    method shutdown (line 326) | public static void shutdown() {
    method submit (line 339) | public static ICancelable submit(Runnable task, int priority) {
    method submit (line 351) | public static ICancelable submit(String groupName, Runnable task, int ...
    method postToMain (line 363) | public static boolean postToMain(Runnable task) {
    method postToMainDelay (line 374) | public static ICancelable postToMainDelay(Runnable task, long delayMil...
    method emergentSubmit (line 384) | public static ICancelable emergentSubmit(Runnable task) {
    method submit (line 394) | public static ICancelable submit(Runnable task) {
    method backgroundSubmit (line 404) | public static ICancelable backgroundSubmit(Runnable task) {
    method ioSubmit (line 414) | public static ICancelable ioSubmit(Runnable task) {
    method groupSubmit (line 425) | public static ICancelable groupSubmit(String groupName, Runnable task) {
    method schedule (line 439) | public static ICancelable schedule(Runnable task, long delay, TimeUnit...
    method scheduleAtFixedRate (line 452) | public static ICancelable scheduleAtFixedRate(Runnable task, long init...
    method scheduleWithFixedDelay (line 465) | public static ICancelable scheduleWithFixedDelay(Runnable task, long i...

FILE: xtask-core/src/main/java/com/xuexiang/xtask/api/TaskChainEngine.java
  class TaskChainEngine (line 47) | public class TaskChainEngine implements ITaskChainEngine {
    method get (line 91) | public static TaskChainEngine get() {
    method get (line 101) | public static TaskChainEngine get(String name) {
    method TaskChainEngine (line 108) | public TaskChainEngine() {
    method TaskChainEngine (line 117) | public TaskChainEngine(String name) {
    method getName (line 121) | @Override
    method setTaskParam (line 126) | @Override
    method setTaskChainCallback (line 132) | @Override
    method addTask (line 142) | @Override
    method addTasks (line 155) | @Override
    method clearTask (line 169) | @Override
    method start (line 183) | @Override
    method start (line 188) | @Override
    method reset (line 210) | @Override
    method destroy (line 222) | @Override
    method isDestroy (line 239) | private boolean isDestroy() {
    method cancel (line 243) | @Override
    method isCancelled (line 259) | @Override
    method onTaskStepCompleted (line 264) | @Override
    method onTaskStepError (line 282) | @Override
    method isNeedChangeToMainThread (line 291) | private boolean isNeedChangeToMainThread() {
    method onTaskChainStart (line 295) | private void onTaskChainStart() {
    method onTaskChainCancelled (line 313) | private void onTaskChainCancelled() {
    method onTaskChainCompleted (line 333) | private void onTaskChainCompleted(final ITaskResult result) {
    method onTaskChainError (line 353) | private void onTaskChainError(final ITaskResult result) {
    method getTaskChainName (line 378) | protected String getTaskChainName() {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/api/step/ConcurrentGroupTaskStep.java
  class ConcurrentGroupTaskStep (line 36) | public class ConcurrentGroupTaskStep extends AbstractGroupTaskStep {
    method get (line 43) | public static ConcurrentGroupTaskStep get() {
    method get (line 53) | public static ConcurrentGroupTaskStep get(@NonNull String name) {
    method get (line 63) | public static ConcurrentGroupTaskStep get(@NonNull ThreadType threadTy...
    method ConcurrentGroupTaskStep (line 67) | public ConcurrentGroupTaskStep() {
    method ConcurrentGroupTaskStep (line 71) | public ConcurrentGroupTaskStep(@NonNull String name) {
    method ConcurrentGroupTaskStep (line 75) | public ConcurrentGroupTaskStep(@NonNull ThreadType threadType) {
    method ConcurrentGroupTaskStep (line 79) | public ConcurrentGroupTaskStep(@NonNull String name, @NonNull ITaskPar...
    method ConcurrentGroupTaskStep (line 83) | public ConcurrentGroupTaskStep(@NonNull String name, @NonNull ThreadTy...
    method doTask (line 87) | @Override
    method onTaskStepCompleted (line 103) | @Override
    method onTaskStepError (line 112) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/api/step/SerialGroupTaskStep.java
  class SerialGroupTaskStep (line 36) | public class SerialGroupTaskStep extends AbstractGroupTaskStep {
    method get (line 43) | public static SerialGroupTaskStep get() {
    method get (line 53) | public static SerialGroupTaskStep get(@NonNull String name) {
    method get (line 63) | public static SerialGroupTaskStep get(@NonNull ThreadType threadType) {
    method SerialGroupTaskStep (line 67) | public SerialGroupTaskStep() {
    method SerialGroupTaskStep (line 71) | public SerialGroupTaskStep(@NonNull String name) {
    method SerialGroupTaskStep (line 75) | public SerialGroupTaskStep(@NonNull ThreadType threadType) {
    method SerialGroupTaskStep (line 79) | public SerialGroupTaskStep(@NonNull String name, @NonNull ITaskParam t...
    method SerialGroupTaskStep (line 83) | public SerialGroupTaskStep(@NonNull String name, @NonNull ThreadType t...
    method doTask (line 87) | @Override
    method onTaskStepCompleted (line 100) | @Override
    method onTaskStepError (line 115) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/api/step/SimpleTaskStep.java
  class SimpleTaskStep (line 35) | public abstract class SimpleTaskStep extends AbstractTaskStep {
    method SimpleTaskStep (line 47) | public SimpleTaskStep() {
    method SimpleTaskStep (line 56) | public SimpleTaskStep(String name) {
    method SimpleTaskStep (line 66) | public SimpleTaskStep(String name, ThreadType threadType) {
    method SimpleTaskStep (line 77) | public SimpleTaskStep(String name, @NonNull ITaskParam taskParam) {
    method SimpleTaskStep (line 89) | public SimpleTaskStep(String name, ThreadType threadType, @NonNull ITa...
    method initTaskStep (line 99) | protected void initTaskStep(String name) {
    method getName (line 107) | @Override
    method isAutoNotify (line 117) | protected boolean isAutoNotify() {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/api/step/XTaskStep.java
  class XTaskStep (line 40) | public class XTaskStep extends AbstractTaskStep {
    method getTask (line 55) | public static XTaskStep getTask(@NonNull TaskCommand command) {
    method getTask (line 66) | public static XTaskStep getTask(@NonNull TaskCommand command, boolean ...
    method getTask (line 77) | public static XTaskStep getTask(@NonNull TaskCommand command, ThreadTy...
    method getTask (line 90) | public static XTaskStep getTask(@NonNull TaskCommand command, @NonNull...
    method getTask (line 104) | public static XTaskStep getTask(@NonNull TaskCommand command, ThreadTy...
    method newBuilder (line 117) | public static Builder newBuilder(@NonNull TaskCommand command) {
    method XTaskStep (line 146) | private XTaskStep(@NonNull String name, @NonNull TaskCommand command, ...
    method getName (line 155) | @Override
    method doTask (line 160) | @Override
    class Builder (line 182) | public static final class Builder {
      method Builder (line 213) | private Builder(@NonNull TaskCommand command) {
      method setName (line 217) | public Builder setName(String name) {
      method setCommand (line 222) | public Builder setCommand(TaskCommand command) {
      method setThreadType (line 227) | public Builder setThreadType(ThreadType threadType) {
      method setTaskParam (line 232) | public Builder setTaskParam(ITaskParam taskParam) {
      method setTaskHandler (line 237) | public Builder setTaskHandler(ITaskStepHandler taskHandler) {
      method setIsAutoNotify (line 242) | public Builder setIsAutoNotify(boolean isAutoNotify) {
      method build (line 247) | public XTaskStep build() {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/ITaskChainCallback.java
  type ITaskChainCallback (line 30) | public interface ITaskChainCallback {
    method isCallBackOnMainThread (line 37) | boolean isCallBackOnMainThread();
    method onTaskChainStart (line 44) | void onTaskChainStart(@NonNull ITaskChainEngine engine);
    method onTaskChainCompleted (line 52) | void onTaskChainCompleted(@NonNull ITaskChainEngine engine, @NonNull I...
    method onTaskChainError (line 60) | void onTaskChainError(@NonNull ITaskChainEngine engine, @NonNull ITask...
    method onTaskChainCancelled (line 67) | void onTaskChainCancelled(@NonNull ITaskChainEngine engine);

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/ITaskChainEngine.java
  type ITaskChainEngine (line 34) | public interface ITaskChainEngine extends ITaskStepLifecycle, IGroupTask...
    method getName (line 41) | @Override
    method setTaskParam (line 50) | ITaskChainEngine setTaskParam(@NonNull ITaskParam taskParam);
    method setTaskChainCallback (line 58) | ITaskChainEngine setTaskChainCallback(ITaskChainCallback iTaskChainCal...
    method start (line 65) | ICancelable start();
    method start (line 73) | ICancelable start(boolean isAddPool);
    method reset (line 78) | void reset();
    method destroy (line 83) | void destroy();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/ThreadType.java
  type ThreadType (line 26) | public enum ThreadType {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/IDataStore.java
  type IDataStore (line 28) | public interface IDataStore {
    method get (line 49) | Object get(String key);
    method put (line 58) | IDataStore put(String key, Object value);
    method getObject (line 67) | <T> T getObject(String key, Class<T> clazz);
    method getObject (line 76) | <T> T getObject(String key, T defaultValue);
    method getString (line 84) | String getString(String key);
    method getString (line 93) | String getString(String key, String defaultValue);
    method getBoolean (line 101) | boolean getBoolean(String key);
    method getBoolean (line 110) | boolean getBoolean(String key, boolean defaultValue);
    method getInt (line 118) | int getInt(String key);
    method getInt (line 127) | int getInt(String key, int defaultValue);
    method getData (line 134) | Map<String, Object> getData();
    method clear (line 139) | void clear();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/ITaskParam.java
  type ITaskParam (line 26) | public interface ITaskParam extends IDataStore {
    method addPath (line 33) | void addPath(String path);
    method addGroupPath (line 42) | void addGroupPath(String path, int index, int total);
    method getPath (line 49) | String getPath();
    method updatePath (line 56) | void updatePath(String path);
    method getDataStore (line 63) | IDataStore getDataStore();
    method updateData (line 70) | void updateData(IDataStore iDataStore);
    method updateParam (line 78) | void updateParam(String path, IDataStore iDataStore);
    method updateParam (line 85) | void updateParam(ITaskParam taskParam);

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/ITaskResult.java
  type ITaskResult (line 26) | public interface ITaskResult {
    method getCode (line 48) | int getCode();
    method getMessage (line 55) | String getMessage();
    method setResult (line 63) | void setResult(int code, String message);
    method saveResult (line 70) | void saveResult(ITaskResult taskResult);
    method saveResultNotPath (line 77) | void saveResultNotPath(ITaskResult taskResult);
    method updateParam (line 84) | void updateParam(ITaskParam taskParam);
    method getDataStore (line 91) | IDataStore getDataStore();
    method getPath (line 98) | String getPath();
    method getDetailMessage (line 105) | String getDetailMessage();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/MapDataStore.java
  class MapDataStore (line 33) | public class MapDataStore implements IDataStore {
    method get (line 42) | @Override
    method getObject (line 50) | @Override
    method getObject (line 55) | @Override
    method getString (line 60) | @Override
    method getString (line 65) | @Override
    method getBoolean (line 71) | @Override
    method getBoolean (line 76) | @Override
    method getInt (line 82) | @Override
    method getInt (line 87) | @Override
    method getData (line 93) | @Override
    method clear (line 98) | @Override
    method put (line 103) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/TaskParam.java
  class TaskParam (line 33) | public class TaskParam implements ITaskParam {
    method get (line 56) | public static TaskParam get() {
    method get (line 67) | public static TaskParam get(String key, Object value) {
    method addPath (line 73) | @Override
    method addGroupPath (line 78) | @Override
    method getPath (line 93) | @Override
    method updatePath (line 98) | @Override
    method getDataStore (line 103) | @Override
    method updateData (line 108) | @Override
    method updateParam (line 122) | @Override
    method updateParam (line 128) | @Override
    method get (line 137) | @Override
    method put (line 142) | @Override
    method getObject (line 148) | @Override
    method getObject (line 153) | @Override
    method getString (line 158) | @Override
    method getString (line 163) | @Override
    method getBoolean (line 168) | @Override
    method getBoolean (line 173) | @Override
    method getInt (line 178) | @Override
    method getInt (line 183) | @Override
    method getData (line 188) | @Override
    method clear (line 193) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/TaskResult.java
  class TaskResult (line 32) | public class TaskResult extends TaskParam implements ITaskResult {
    method succeed (line 41) | public static TaskResult succeed() {
    method failed (line 50) | public static TaskResult failed() {
    method failed (line 60) | public static TaskResult failed(int code) {
    method failed (line 71) | public static TaskResult failed(int code, String message) {
    method TaskResult (line 88) | public TaskResult() {
    method TaskResult (line 97) | public TaskResult(@NonNull ITaskParam taskParam) {
    method TaskResult (line 106) | public TaskResult(@NonNull ITaskResult taskResult) {
    method TaskResult (line 117) | public TaskResult(int code, String message) {
    method getCode (line 121) | @Override
    method setCode (line 126) | public TaskResult setCode(int code) {
    method getMessage (line 131) | @Override
    method setMessage (line 136) | public TaskResult setMessage(String message) {
    method setResult (line 147) | @Override
    method saveResult (line 153) | @Override
    method saveResultNotPath (line 163) | @Override
    method getDetailMessage (line 173) | @Override
    method toString (line 178) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/IGroupTaskStep.java
  type IGroupTaskStep (line 28) | public interface IGroupTaskStep {
    method addTask (line 36) | IGroupTaskStep addTask(ITaskStep taskStep);
    method addTasks (line 44) | IGroupTaskStep addTasks(List<ITaskStep> taskStepList);
    method clearTask (line 49) | void clearTask();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStep.java
  type ITaskStep (line 33) | public interface ITaskStep extends Runnable, ICancelable, ITaskStepContr...
    method setTaskStepLifecycle (line 41) | ITaskStep setTaskStepLifecycle(@NonNull ITaskStepLifecycle taskStepLif...
    method setTaskStepHandler (line 49) | ITaskStep setTaskStepHandler(@NonNull ITaskStepHandler taskStepHandler);
    method setThreadType (line 57) | ITaskStep setThreadType(@NonNull ThreadType threadType);
    method setTaskParam (line 65) | ITaskStep setTaskParam(@NonNull ITaskParam taskParam);
    method getThreadType (line 72) | @NonNull
    method accept (line 80) | boolean accept();
    method prepareTask (line 87) | void prepareTask(TaskParam taskParam);
    method setCancelable (line 94) | void setCancelable(ICancelable cancelable);
    method doTask (line 101) | void doTask() throws Exception;
    method setIsRunning (line 108) | void setIsRunning(boolean isRunning);
    method isRunning (line 115) | boolean isRunning();
    method isPending (line 122) | boolean isPending();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepController.java
  type ITaskStepController (line 31) | public interface ITaskStepController {
    method getName (line 38) | String getName();
    method getTaskParam (line 45) | @NonNull
    method notifyTaskSucceed (line 53) | void notifyTaskSucceed(@NonNull ITaskResult result);
    method notifyTaskFailed (line 60) | void notifyTaskFailed(@NonNull ITaskResult result);
    method recycle (line 65) | void recycle();

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepHandler.java
  type ITaskStepHandler (line 28) | public interface ITaskStepHandler {
    method beforeTask (line 35) | void beforeTask(@NonNull ITaskStep step);
    method afterTask (line 42) | void afterTask(@NonNull ITaskStep step);
    method onTaskException (line 50) | void onTaskException(@NonNull ITaskStep step, Exception exception);
    method accept (line 58) | boolean accept(@NonNull ITaskStep step);
    method handleTaskSucceed (line 65) | void handleTaskSucceed(@NonNull ITaskStep step);
    method handleTaskFailed (line 72) | void handleTaskFailed(@NonNull ITaskStep step);
    method handleTaskCancelled (line 79) | void handleTaskCancelled(@NonNull ITaskStep step);

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepLifecycle.java
  type ITaskStepLifecycle (line 30) | public interface ITaskStepLifecycle {
    method onTaskStepCompleted (line 38) | void onTaskStepCompleted(@NonNull ITaskStep step, @NonNull ITaskResult...
    method onTaskStepError (line 46) | void onTaskStepError(@NonNull ITaskStep step, @NonNull ITaskResult res...

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AbstractGroupTaskStep.java
  class AbstractGroupTaskStep (line 43) | public abstract class AbstractGroupTaskStep extends AbstractTaskStep imp...
    method AbstractGroupTaskStep (line 79) | public AbstractGroupTaskStep() {
    method AbstractGroupTaskStep (line 88) | public AbstractGroupTaskStep(@NonNull String name) {
    method AbstractGroupTaskStep (line 97) | public AbstractGroupTaskStep(@NonNull ThreadType threadType) {
    method AbstractGroupTaskStep (line 108) | public AbstractGroupTaskStep(@NonNull String name, @NonNull ITaskParam...
    method AbstractGroupTaskStep (line 119) | public AbstractGroupTaskStep(@NonNull String name, @NonNull ThreadType...
    method addTask (line 124) | @Override
    method addTasks (line 133) | @Override
    method setTaskParam (line 143) | @Override
    method setThreadType (line 150) | @Override
    method initGroupTask (line 159) | protected void initGroupTask() {
    method prepareTask (line 165) | @Override
    method clearTask (line 171) | @Override
    method recycle (line 182) | @Override
    method cancel (line 189) | @Override
    method getTaskParam (line 200) | @NonNull
    method getName (line 206) | @Override
    method getTasks (line 211) | public List<ITaskStep> getTasks() {
    method getResult (line 215) | public TaskResult getResult() {
    method getTaskLogName (line 219) | @Override
    method generationGroupName (line 229) | @NonNull

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AbstractTaskStep.java
  class AbstractTaskStep (line 41) | public abstract class AbstractTaskStep implements ITaskStep {
    method AbstractTaskStep (line 86) | public AbstractTaskStep() {
    method AbstractTaskStep (line 95) | public AbstractTaskStep(ThreadType threadType) {
    method AbstractTaskStep (line 104) | public AbstractTaskStep(@NonNull ITaskParam taskParam) {
    method AbstractTaskStep (line 114) | public AbstractTaskStep(ThreadType threadType, @NonNull ITaskParam tas...
    method setTaskStepLifecycle (line 119) | @Override
    method setTaskStepHandler (line 125) | @Override
    method setThreadType (line 131) | @Override
    method setTaskParam (line 137) | @Override
    method getThreadType (line 143) | @NonNull
    method getTaskParam (line 149) | @NonNull
    method setCancelable (line 155) | @Override
    method setIsRunning (line 160) | @Override
    method isRunning (line 165) | @Override
    method isPending (line 170) | @Override
    method accept (line 175) | @Override
    method prepareTask (line 183) | @Override
    method notifyTaskSucceed (line 188) | @Override
    method notifyTaskFailed (line 210) | @Override
    method recycle (line 228) | @Override
    method cancel (line 240) | @Override
    method isCancelled (line 257) | @Override
    method run (line 262) | @Override
    method processTask (line 284) | protected void processTask() throws Exception {
    method updateProcessTaskPath (line 300) | private void updateProcessTaskPath() {
    method getTaskRunningDetailLogInfo (line 306) | private String getTaskRunningDetailLogInfo() {
    method getTaskLogName (line 319) | protected String getTaskLogName() {
    method notifyTaskSucceed (line 328) | public void notifyTaskSucceed() {
    method notifyTaskFailed (line 335) | public void notifyTaskFailed() {
    method notifyTaskFailed (line 344) | public void notifyTaskFailed(int code) {
    method notifyTaskFailed (line 354) | public void notifyTaskFailed(int code, String message) {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AutoDestroyTaskChainCallback.java
  class AutoDestroyTaskChainCallback (line 32) | public class AutoDestroyTaskChainCallback implements ITaskChainCallback {
    method isCallBackOnMainThread (line 34) | @Override
    method onTaskChainStart (line 39) | @Override
    method onTaskChainCompleted (line 44) | @Override
    method onTaskChainError (line 49) | @Override
    method onTaskChainCancelled (line 54) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AutoNotifyTaskStepHandler.java
  class AutoNotifyTaskStepHandler (line 33) | public class AutoNotifyTaskStepHandler implements ITaskStepHandler {
    method beforeTask (line 34) | @Override
    method afterTask (line 39) | @Override
    method onTaskException (line 44) | @Override
    method accept (line 49) | @Override
    method handleTaskSucceed (line 54) | @Override
    method handleTaskFailed (line 59) | @Override
    method handleTaskCancelled (line 64) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/TaskChainCallbackAdapter.java
  class TaskChainCallbackAdapter (line 32) | public abstract class TaskChainCallbackAdapter implements ITaskChainCall...
    method isCallBackOnMainThread (line 34) | @Override
    method onTaskChainStart (line 39) | @Override
    method onTaskChainError (line 44) | @Override
    method onTaskChainCancelled (line 49) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/TaskCommand.java
  class TaskCommand (line 34) | public abstract class TaskCommand implements ITaskStepController {
    method setTaskStepResultController (line 47) | public TaskCommand setTaskStepResultController(ITaskStepController con...
    method notifyTaskSucceed (line 55) | public void notifyTaskSucceed() {
    method notifyTaskFailed (line 62) | public void notifyTaskFailed() {
    method notifyTaskFailed (line 71) | public void notifyTaskFailed(int code) {
    method notifyTaskFailed (line 81) | public void notifyTaskFailed(int code, String message) {
    method notifyTaskSucceed (line 85) | @Override
    method notifyTaskFailed (line 92) | @Override
    method getName (line 99) | @Override
    method getTaskParam (line 104) | @NonNull
    method run (line 115) | public abstract void run() throws Exception;
    method recycle (line 117) | @Override

FILE: xtask-core/src/main/java/com/xuexiang/xtask/utils/CancellerPoolUtils.java
  class CancellerPoolUtils (line 32) | public final class CancellerPoolUtils {
    method CancellerPoolUtils (line 36) | private CancellerPoolUtils() {
    method setCancellerPool (line 45) | public static void setCancellerPool(ICancellerPool sCancellerPool) {
    method add (line 56) | public static boolean add(String name, ICancelable cancelable) {
    method remove (line 66) | public static boolean remove(String name) {
    method cancel (line 76) | public static boolean cancel(String name) {
    method cancel (line 85) | public static void cancel(String... names) {
    method cancel (line 95) | public static void cancel(Collection<String> names) {
    method cancelAll (line 102) | public static void cancelAll() {
    method clear (line 111) | public static void clear(boolean ifNeedCancel) {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/utils/CommonUtils.java
  class CommonUtils (line 31) | public final class CommonUtils {
    method CommonUtils (line 35) | private CommonUtils() {
    method cast (line 47) | public static <T> T cast(final Object object, Class<T> clazz) {
    method cast (line 59) | public static <T> T cast(Object object, T defaultValue) {
    method isEmpty (line 75) | public static boolean isEmpty(final CharSequence s) {
    method isEmpty (line 85) | public static <E> boolean isEmpty(final Collection<E> collection) {
    method isEmpty (line 95) | public static boolean isEmpty(final Map obj) {
    method requireNonNull (line 107) | public static <T> T requireNonNull(final T object, final String messag...
    method getSize (line 120) | public static <E> int getSize(final Collection<E> collection) {

FILE: xtask-core/src/main/java/com/xuexiang/xtask/utils/TaskUtils.java
  class TaskUtils (line 36) | public final class TaskUtils {
    method TaskUtils (line 40) | private TaskUtils() {
    method isMainThread (line 49) | public static boolean isMainThread() {
    method runOnMainThread (line 58) | public static void runOnMainThread(Runnable runnable) {
    method findNextTaskStep (line 69) | public static ITaskStep findNextTaskStep(List<ITaskStep> taskStepList,...
    method findTaskStepSize (line 92) | public static int findTaskStepSize(List<ITaskStep> taskStepList) {
    method executeTask (line 110) | public static ICancelable executeTask(ITaskStep taskStep) {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/logger/ILogger.java
  type ILogger (line 26) | public interface ILogger {
    method log (line 36) | void log(int priority, String tag, String message, Throwable t);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/logger/LogcatLogger.java
  class LogcatLogger (line 33) | public class LogcatLogger implements ILogger {
    method log (line 48) | @Override
    method getStackTraceString (line 67) | public static String getStackTraceString(Throwable t) {
    method log (line 85) | public void log(int priority, String tag, String message) {
    method logSub (line 109) | private void logSub(int priority, @NonNull String tag, @NonNull String...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/logger/TaskLogger.java
  class TaskLogger (line 31) | public final class TaskLogger {
    method TaskLogger (line 33) | private TaskLogger() {
    method getLogTag (line 80) | public static String getLogTag(@NonNull Class<?> clazz) {
    method getLogTag (line 90) | public static String getLogTag(@NonNull String className) {
    method setLogger (line 99) | public static void setLogger(@NonNull ILogger logger) {
    method setTag (line 108) | public static void setTag(String tag) {
    method setDebug (line 117) | public static void setDebug(boolean isDebug) {
    method setPriority (line 126) | public static void setPriority(int priority) {
    method setIsLogThreadName (line 135) | public static void setIsLogThreadName(boolean isLogThreadName) {
    method isLogThreadName (line 144) | public static boolean isLogThreadName() {
    method debug (line 155) | public static void debug(boolean isDebug) {
    method debug (line 164) | public static void debug(String tag) {
    method v (line 183) | public static void v(String msg) {
    method vTag (line 195) | public static void vTag(String tag, String msg) {
    method d (line 206) | public static void d(String msg) {
    method dTag (line 218) | public static void dTag(String tag, String msg) {
    method i (line 229) | public static void i(String msg) {
    method iTag (line 241) | public static void iTag(String tag, String msg) {
    method w (line 252) | public static void w(String msg) {
    method wTag (line 264) | public static void wTag(String tag, String msg) {
    method e (line 275) | public static void e(String msg) {
    method eTag (line 287) | public static void eTag(String tag, String msg) {
    method e (line 298) | public static void e(Throwable t) {
    method eTag (line 310) | public static void eTag(String tag, Throwable t) {
    method e (line 323) | public static void e(String msg, Throwable t) {
    method eTag (line 336) | public static void eTag(String tag, String msg, Throwable t) {
    method wtf (line 347) | public static void wtf(String msg) {
    method wtfTag (line 359) | public static void wtfTag(String tag, String msg) {
    method log (line 371) | public static void log(int priority, String tag, String msg) {
    method enableLog (line 383) | private static boolean enableLog(int logPriority) {
    method isDebug (line 392) | public static boolean isDebug() {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/XTaskExecutor.java
  class XTaskExecutor (line 38) | public class XTaskExecutor implements IPriorityExecutorCore, ICategoryEx...
    method get (line 60) | public static XTaskExecutor get() {
    method XTaskExecutor (line 74) | private XTaskExecutor() {
    method setPriorityExecutorCore (line 86) | public XTaskExecutor setPriorityExecutorCore(@NonNull IPriorityExecuto...
    method setCategoryExecutorCore (line 97) | public XTaskExecutor setCategoryExecutorCore(@NonNull ICategoryExecuto...
    method setScheduledExecutorCore (line 108) | public XTaskExecutor setScheduledExecutorCore(@NonNull IScheduledExecu...
    method shutdown (line 113) | @Override
    method submit (line 122) | @Override
    method submit (line 127) | @Override
    method postToMain (line 134) | @Override
    method postToMainDelay (line 139) | @Override
    method emergentSubmit (line 144) | @Override
    method submit (line 149) | @Override
    method backgroundSubmit (line 154) | @Override
    method ioSubmit (line 159) | @Override
    method groupSubmit (line 164) | @Override
    method schedule (line 171) | @Override
    method scheduleAtFixedRate (line 176) | @Override
    method scheduleWithFixedDelay (line 181) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/ICategoryExecutorCore.java
  type ICategoryExecutorCore (line 28) | public interface ICategoryExecutorCore extends IExecutorCore {
    method postToMain (line 36) | boolean postToMain(Runnable task);
    method postToMainDelay (line 45) | ICancelable postToMainDelay(Runnable task, long delayMillis);
    method emergentSubmit (line 53) | ICancelable emergentSubmit(Runnable task);
    method submit (line 61) | ICancelable submit(Runnable task);
    method backgroundSubmit (line 69) | ICancelable backgroundSubmit(Runnable task);
    method ioSubmit (line 77) | ICancelable ioSubmit(Runnable task);
    method groupSubmit (line 86) | ICancelable groupSubmit(String groupName, Runnable task);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IExecutorCore.java
  type IExecutorCore (line 26) | public interface IExecutorCore {
    method shutdown (line 31) | void shutdown();

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IPriorityExecutorCore.java
  type IPriorityExecutorCore (line 28) | public interface IPriorityExecutorCore extends IExecutorCore {
    method submit (line 37) | ICancelable submit(Runnable task, int priority);
    method submit (line 47) | ICancelable submit(String groupName, Runnable task, int priority);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IScheduledExecutorCore.java
  type IScheduledExecutorCore (line 30) | public interface IScheduledExecutorCore extends IExecutorCore {
    method schedule (line 40) | ICancelable schedule(Runnable task, long delay, TimeUnit unit);
    method scheduleAtFixedRate (line 51) | ICancelable scheduleAtFixedRate(Runnable task, long initialDelay, long...
    method scheduleWithFixedDelay (line 62) | ICancelable scheduleWithFixedDelay(Runnable task, long initialDelay, l...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/CategoryExecutorCore.java
  class CategoryExecutorCore (line 50) | public class CategoryExecutorCore implements ICategoryExecutorCore {
    method postToMain (line 81) | @Override
    method postToMainDelay (line 90) | @Override
    method emergentSubmit (line 95) | @Override
    method submit (line 100) | @Override
    method backgroundSubmit (line 105) | @Override
    method ioSubmit (line 110) | @Override
    method groupSubmit (line 115) | @Override
    method shutdown (line 120) | @Override
    method submitTask (line 142) | private ICancelable submitTask(@NonNull DefaultThreadPoolExecutor exec...
    method getTargetExecutor (line 152) | @NonNull
    method getEmergentExecutor (line 163) | private DefaultThreadPoolExecutor getEmergentExecutor() {
    method getNormalExecutor (line 175) | private DefaultThreadPoolExecutor getNormalExecutor() {
    method getBackgroundExecutor (line 185) | private DefaultThreadPoolExecutor getBackgroundExecutor(int priority) {
    method getIoExecutor (line 195) | private DefaultThreadPoolExecutor getIoExecutor() {
    method getGroupExecutor (line 210) | @NonNull

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/PriorityExecutorCore.java
  class PriorityExecutorCore (line 40) | public class PriorityExecutorCore implements IPriorityExecutorCore, IExe...
    method submit (line 50) | @Override
    method submit (line 55) | @Override
    method shutdown (line 60) | @Override
    method submitTask (line 76) | private ICancelable submitTask(@NonNull PriorityThreadPoolExecutor exe...
    method getThreadPoolExecutor (line 86) | @NonNull

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/ScheduledExecutorCore.java
  class ScheduledExecutorCore (line 35) | public class ScheduledExecutorCore implements IScheduledExecutorCore {
    method schedule (line 39) | @Override
    method scheduleAtFixedRate (line 44) | @Override
    method scheduleWithFixedDelay (line 49) | @Override
    method shutdown (line 54) | @Override
    method getThreadPoolExecutor (line 65) | @NonNull

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/DefaultScheduledThreadPoolExecutor.java
  class DefaultScheduledThreadPoolExecutor (line 37) | public class DefaultScheduledThreadPoolExecutor extends BaseScheduledThr...
    method getDefault (line 44) | public static DefaultScheduledThreadPoolExecutor getDefault() {
    method newBuilder (line 53) | public static Builder newBuilder() {
    method newBuilder (line 63) | public static Builder newBuilder(int corePoolSize) {
    method DefaultScheduledThreadPoolExecutor (line 74) | public DefaultScheduledThreadPoolExecutor(int corePoolSize, ThreadFact...
    method decorateTask (line 78) | @Override
    method decorateTask (line 83) | @Override
    method schedule (line 88) | @Override
    method scheduleAtFixedRate (line 93) | @Override
    method scheduleWithFixedDelay (line 98) | @Override
    class DefaultScheduledFuture (line 109) | public static class DefaultScheduledFuture<V> extends FutureTask<V> im...
      method DefaultScheduledFuture (line 113) | DefaultScheduledFuture(Callable<V> callable, RunnableScheduledFuture...
      method DefaultScheduledFuture (line 118) | DefaultScheduledFuture(Runnable runnable, RunnableScheduledFuture<V>...
      method cancel (line 123) | @Override
      method getDelay (line 128) | @Override
      method compareTo (line 133) | @Override
      method isPeriodic (line 138) | @Override
      method cancel (line 143) | @Override
      method run (line 148) | @Override
    class Builder (line 159) | public static final class Builder {
      method Builder (line 184) | public Builder() {
      method Builder (line 193) | public Builder(int corePoolSize) {
      method setCorePoolSize (line 197) | public Builder setCorePoolSize(int corePoolSize) {
      method setThreadFactory (line 202) | public Builder setThreadFactory(ThreadFactory threadFactory) {
      method setHandler (line 207) | public Builder setHandler(RejectedExecutionHandler handler) {
      method build (line 217) | public DefaultScheduledThreadPoolExecutor build() {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/DefaultThreadPoolExecutor.java
  class DefaultThreadPoolExecutor (line 40) | public class DefaultThreadPoolExecutor extends BaseThreadPoolExecutor {
    method getDefault (line 47) | public static DefaultThreadPoolExecutor getDefault() {
    method newBuilder (line 56) | public static DefaultThreadPoolExecutor.Builder newBuilder() {
    method newBuilder (line 66) | public static Builder newBuilder(int corePoolSize) {
    method newBuilder (line 79) | public static Builder newBuilder(int corePoolSize, int maximumPoolSize...
    method DefaultThreadPoolExecutor (line 94) | private DefaultThreadPoolExecutor(int corePoolSize, int maximumPoolSiz...
    method newTaskFor (line 98) | @Override
    method newTaskFor (line 103) | @Override
    method submit (line 108) | @Override
    class DefaultFuture (line 119) | public static class DefaultFuture<V> extends FutureTask<V> implements ...
      method DefaultFuture (line 121) | DefaultFuture(Callable<V> callable) {
      method DefaultFuture (line 125) | DefaultFuture(Runnable runnable, V result) {
      method cancel (line 129) | @Override
    class Builder (line 141) | public static final class Builder {
      method Builder (line 190) | public Builder() {
      method Builder (line 199) | public Builder(int corePoolSize) {
      method Builder (line 211) | public Builder(int corePoolSize, int maximumPoolSize, long keepAlive...
      method setCorePoolSize (line 218) | public Builder setCorePoolSize(int corePoolSize) {
      method setMaximumPoolSize (line 223) | public Builder setMaximumPoolSize(int maximumPoolSize) {
      method setKeepAliveTime (line 228) | public Builder setKeepAliveTime(long keepAliveTime) {
      method setUnit (line 233) | public Builder setUnit(TimeUnit unit) {
      method setWorkQueue (line 238) | public Builder setWorkQueue(BlockingQueue<Runnable> workQueue) {
      method setThreadFactory (line 243) | public Builder setThreadFactory(ThreadFactory threadFactory) {
      method setHandler (line 248) | public Builder setHandler(RejectedExecutionHandler handler) {
      method build (line 258) | public DefaultThreadPoolExecutor build() {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/PriorityThreadPoolExecutor.java
  class PriorityThreadPoolExecutor (line 52) | public class PriorityThreadPoolExecutor extends BaseThreadPoolExecutor {
    method getDefault (line 61) | public static PriorityThreadPoolExecutor getDefault() {
    method newBuilder (line 70) | public static Builder newBuilder() {
    method newBuilder (line 80) | public static Builder newBuilder(int corePoolSize) {
    method newBuilder (line 92) | public static Builder newBuilder(int corePoolSize, long keepAliveTime,...
    method PriorityThreadPoolExecutor (line 107) | private PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSi...
    method execute (line 118) | public IPriorityRunnable execute(Runnable command, int priority) {
    method submit (line 135) | public IPriorityFuture<?> submit(Runnable task, int priority) {
    method submit (line 150) | public <T> IPriorityFuture<T> submit(Runnable task, T result, int prio...
    method submit (line 165) | public <T> IPriorityFuture<T> submit(Callable<T> task, int priority) {
    method newTaskFor (line 172) | @Override
    method newTaskFor (line 177) | @Override
    method execute (line 188) | @Override
    method submit (line 208) | @Override
    method submit (line 227) | @Override
    method submit (line 245) | @Override
    class Builder (line 261) | public static final class Builder {
      method Builder (line 302) | public Builder() {
      method Builder (line 311) | public Builder(int corePoolSize) {
      method Builder (line 322) | public Builder(int corePoolSize, long keepAliveTime, TimeUnit unit) {
      method setCorePoolSize (line 328) | public Builder setCorePoolSize(int corePoolSize) {
      method setKeepAliveTime (line 333) | public Builder setKeepAliveTime(long keepAliveTime) {
      method setUnit (line 338) | public Builder setUnit(TimeUnit unit) {
      method setWorkQueue (line 343) | public Builder setWorkQueue(PriorityBlockingQueue<Runnable> workQueu...
      method setThreadFactory (line 348) | public Builder setThreadFactory(ThreadFactory threadFactory) {
      method setHandler (line 353) | public Builder setHandler(RejectedExecutionHandler handler) {
      method build (line 363) | public PriorityThreadPoolExecutor build() {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/TaskRecordPolicy.java
  class TaskRecordPolicy (line 31) | public class TaskRecordPolicy implements RejectedExecutionHandler {
    method rejectedExecution (line 35) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/TaskThreadFactory.java
  class TaskThreadFactory (line 36) | public class TaskThreadFactory implements ThreadFactory {
    method getFactory (line 67) | public static TaskThreadFactory getFactory(@NonNull String factoryName) {
    method getFactory (line 78) | public static TaskThreadFactory getFactory(@NonNull String factoryName...
    method TaskThreadFactory (line 88) | private TaskThreadFactory(@NonNull String factoryName, @IntRange(from ...
    method newThread (line 95) | @Override
    method getTaskPoolNumber (line 117) | private int getTaskPoolNumber(int priority) {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/base/BaseScheduledThreadPoolExecutor.java
  class BaseScheduledThreadPoolExecutor (line 42) | public class BaseScheduledThreadPoolExecutor extends ScheduledThreadPool...
    method BaseScheduledThreadPoolExecutor (line 51) | public BaseScheduledThreadPoolExecutor(int corePoolSize) {
    method BaseScheduledThreadPoolExecutor (line 61) | public BaseScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory...
    method BaseScheduledThreadPoolExecutor (line 71) | public BaseScheduledThreadPoolExecutor(int corePoolSize, RejectedExecu...
    method BaseScheduledThreadPoolExecutor (line 82) | public BaseScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory...
    method beforeExecute (line 86) | @Override
    method afterExecute (line 105) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/base/BaseThreadPoolExecutor.java
  class BaseThreadPoolExecutor (line 53) | public class BaseThreadPoolExecutor extends ThreadPoolExecutor {
    method BaseThreadPoolExecutor (line 66) | public BaseThreadPoolExecutor(int corePoolSize, int maximumPoolSize, l...
    method BaseThreadPoolExecutor (line 80) | public BaseThreadPoolExecutor(int corePoolSize, int maximumPoolSize, l...
    method BaseThreadPoolExecutor (line 94) | public BaseThreadPoolExecutor(int corePoolSize, int maximumPoolSize, l...
    method BaseThreadPoolExecutor (line 109) | public BaseThreadPoolExecutor(int corePoolSize, int maximumPoolSize, l...
    method beforeExecute (line 113) | @Override
    method afterExecute (line 132) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/CancelHandlerRunnable.java
  class CancelHandlerRunnable (line 33) | public class CancelHandlerRunnable implements Runnable, ICancelable {
    method get (line 42) | public static CancelHandlerRunnable get(@NonNull Handler handler, @Non...
    method CancelHandlerRunnable (line 58) | private CancelHandlerRunnable(@NonNull Handler handler, @NonNull Runna...
    method startDelayed (line 69) | public ICancelable startDelayed(long delayMillis) {
    method cancel (line 77) | @Override
    method isCancelled (line 90) | @Override
    method run (line 95) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICancelable.java
  type ICancelable (line 26) | public interface ICancelable {
    method cancel (line 31) | void cancel();
    method isCancelled (line 38) | boolean isCancelled();

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICanceller.java
  type ICanceller (line 26) | public interface ICanceller extends ICancelable {
    method getName (line 33) | String getName();

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICancellerPool.java
  type ICancellerPool (line 28) | public interface ICancellerPool {
    method add (line 37) | boolean add(String name, ICancelable cancelable);
    method remove (line 45) | boolean remove(String name);
    method cancel (line 53) | boolean cancel(String name);
    method cancel (line 60) | void cancel(String... names);
    method cancel (line 67) | void cancel(Collection<String> names);
    method cancelAll (line 72) | void cancelAll();
    method clear (line 79) | void clear(boolean ifNeedCancel);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/IFuture.java
  type IFuture (line 28) | public interface IFuture<T> extends Future<T>, ICancelable {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/IScheduledFuture.java
  type IScheduledFuture (line 28) | public interface IScheduledFuture<T> extends RunnableScheduledFuture<T>,...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/TaskCancellerPool.java
  class TaskCancellerPool (line 32) | public final class TaskCancellerPool implements ICancellerPool {
    method add (line 36) | @Override
    method remove (line 44) | @Override
    method cancel (line 52) | @Override
    method cancel (line 63) | @Override
    method cancel (line 70) | @Override
    method cancelAll (line 77) | @Override
    method clear (line 86) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriority.java
  type IPriority (line 26) | public interface IPriority {
    method priority (line 33) | int priority();
    method priority (line 40) | void priority(int priority);
    method getId (line 47) | long getId();
    method setId (line 54) | void setId(long id);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityCallable.java
  type IPriorityCallable (line 28) | public interface IPriorityCallable<V> extends IPriorityComparable<IPrior...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityComparable.java
  type IPriorityComparable (line 26) | public interface IPriorityComparable<T> extends IPriority, Comparable<T> {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityFuture.java
  type IPriorityFuture (line 28) | public interface IPriorityFuture<V> extends IPriorityComparable<IPriorit...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityRunnable.java
  type IPriorityRunnable (line 26) | public interface IPriorityRunnable extends IPriorityComparable<IPriority...

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityStrategy.java
  type IPriorityStrategy (line 26) | public interface IPriorityStrategy {
    method compare (line 35) | int compare(IPriority priority, IPriority other);

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityCallable.java
  class DefaultPriorityCallable (line 32) | public class DefaultPriorityCallable<V> implements IPriorityCallable<V> {
    method DefaultPriorityCallable (line 42) | public DefaultPriorityCallable(IPriority priority, Callable<V> callabl...
    method priority (line 48) | @Override
    method getId (line 55) | @Override
    method setId (line 60) | @Override
    method priority (line 67) | @Override
    method compareTo (line 72) | @Override
    method call (line 77) | @Override
    method toString (line 85) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityFuture.java
  class DefaultPriorityFuture (line 33) | public class DefaultPriorityFuture<V> extends FutureTask<V> implements I...
    method DefaultPriorityFuture (line 40) | public DefaultPriorityFuture(Callable<V> callable) {
    method DefaultPriorityFuture (line 48) | public DefaultPriorityFuture(Runnable runnable, V result) {
    method priority (line 56) | @Override
    method getId (line 63) | @Override
    method setId (line 68) | @Override
    method priority (line 75) | @Override
    method compareTo (line 80) | @Override
    method toString (line 85) | @Override
    method cancel (line 92) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityRunnable.java
  class DefaultPriorityRunnable (line 30) | public class DefaultPriorityRunnable implements IPriorityRunnable {
    method DefaultPriorityRunnable (line 40) | public DefaultPriorityRunnable(IPriority priority, Runnable runnable) {
    method priority (line 46) | @Override
    method getId (line 53) | @Override
    method setId (line 58) | @Override
    method priority (line 65) | @Override
    method compareTo (line 70) | @Override
    method run (line 75) | @Override
    method toString (line 82) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityStrategy.java
  class DefaultPriorityStrategy (line 30) | public class DefaultPriorityStrategy implements IPriorityStrategy {
    method compare (line 31) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/Priority.java
  class Priority (line 28) | public class Priority implements IPriority {
    method Priority (line 40) | public Priority() {
    method Priority (line 44) | public Priority(int priority) {
    method priority (line 48) | @Override
    method priority (line 53) | @Override
    method getId (line 58) | @Override
    method setId (line 63) | @Override
    method toString (line 68) | @Override

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/CancelUtils.java
  class CancelUtils (line 30) | public final class CancelUtils {
    method cancel (line 39) | public static boolean cancel(ICancelable cancelable) {
    method cancel (line 52) | public static void cancel(Collection<ICancelable> cancelables) {
    method cancel (line 66) | public static void cancel(ICancelable... cancelables) {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/ExecutorUtils.java
  class ExecutorUtils (line 31) | public final class ExecutorUtils {
    method ExecutorUtils (line 33) | private ExecutorUtils() {
    method shutdown (line 42) | public static void shutdown(ExecutorService executor) {
    method shutdown (line 53) | public static void shutdown(Collection<? extends ExecutorService> exec...
    method isMainThread (line 67) | public static boolean isMainThread() {

FILE: xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/PriorityUtils.java
  class PriorityUtils (line 32) | public final class PriorityUtils {
    method PriorityUtils (line 38) | private PriorityUtils() {
    method generateId (line 47) | public static long generateId() {
    method setPriorityStrategy (line 56) | public static void setPriorityStrategy(IPriorityStrategy sPriorityStra...
    method compare (line 67) | public static int compare(IPriority priority, IPriority other) {
    method formatStackTrace (line 79) | public static String formatStackTrace(StackTraceElement[] stackTrace) {
Condensed preview — 173 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (899K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 121,
    "preview": "# These are supported funding model platforms\n\ncustom: https://gitee.com/xuexiangjys/Resource/blob/master/doc/sponsor.md"
  },
  {
    "path": ".gitignore",
    "chars": 241,
    "preview": "*.iml\n.gradle\n/LocalRepository\n/keystores\n/local.properties\n/.idea/caches\n/.idea/codeStyles\n/.idea/inspectionProfiles\n/."
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "chars": 203,
    "preview": "<component name=\"CopyrightManager\">\n  <settings default=\"xuexiang\">\n    <module2copyright>\n      <element module=\"Projec"
  },
  {
    "path": ".idea/copyright/xuexiang.xml",
    "chars": 829,
    "preview": "<component name=\"CopyrightManager\">\n  <copyright>\n    <option name=\"notice\" value=\"Copyright (C) &amp;#36;today.year xue"
  },
  {
    "path": "JitPackUpload.gradle",
    "chars": 1240,
    "preview": "apply plugin: 'com.github.dcendents.android-maven'\n\n// 指定group,com.github.<用户名>,这里我默认填写的是我的github账号,请换成你自己的。\ngroup='com."
  },
  {
    "path": "LICENSE",
    "chars": 10256,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "README.md",
    "chars": 12961,
    "preview": "# XTask\n[![](https://jitpack.io/v/xuexiangjys/XTask.svg)](https://jitpack.io/#xuexiangjys/XTask)\n[![api](https://img.shi"
  },
  {
    "path": "app/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "chars": 3443,
    "preview": "apply plugin: 'com.android.application'\napply plugin: 'img-optimizer'\n//打包时,记得设置true启用\nif (isNeedPackage.toBoolean() && "
  },
  {
    "path": "app/channel",
    "chars": 169,
    "preview": "# 美团\nmeituan\n# 三星\nsamsungapps\n# 小米\nxiaomi\n# 91助手\n91com\n# 魅族\nmeizu\n# 豌豆荚\nwandou\n# Google Play\ngoogleplay\n# 百度\nbaidu\n# 360"
  },
  {
    "path": "app/multiple-channel.gradle",
    "chars": 346,
    "preview": "apply plugin: 'walle'\n\nwalle {\n    // 指定渠道包的输出路径\n    apkOutputFolder = new File(\"${project.buildDir}/outputs/channels\")\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 7721,
    "preview": "#=========================================基础不变的混淆配置=========================================##\n#指定代码的压缩级别\n-optimizationp"
  },
  {
    "path": "app/src/androidTest/java/com/xuexiang/xtaskdemo/ExampleInstrumentedTest.java",
    "chars": 766,
    "preview": "package com.xuexiang.xtaskdemo;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegis"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 1891,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:to"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/MyApp.java",
    "chars": 1658,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/activity/MainActivity.java",
    "chars": 1081,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/core/BaseActivity.java",
    "chars": 2885,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/core/BaseContainerFragment.java",
    "chars": 3641,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/core/BaseFragment.java",
    "chars": 9401,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/core/BaseSimpleListFragment.java",
    "chars": 8238,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/core/SimpleListAdapter.java",
    "chars": 2374,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/CustomTaskFragment.java",
    "chars": 6634,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/MainFragment.java",
    "chars": 2137,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/TestThreadPoolFragment.java",
    "chars": 5777,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/UseCaseFragment.java",
    "chars": 1368,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskStepFragment.java",
    "chars": 13015,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/XTaskThreadFragment.java",
    "chars": 5527,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/Job.java",
    "chars": 1775,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/JobTask.java",
    "chars": 1266,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepATask.java",
    "chars": 1375,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/task/StepBTask.java",
    "chars": 1460,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/AppStartFragment.java",
    "chars": 4675,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ComplexBusinessFragment.java",
    "chars": 8930,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/ConcurrentProcessFragment.java",
    "chars": 11355,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/AbstractMockJob.java",
    "chars": 1420,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/LongTimeJob.java",
    "chars": 1103,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/SingleJob.java",
    "chars": 1185,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/job/TopPriorityJob.java",
    "chars": 1113,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/AsyncInitTask.java",
    "chars": 1562,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/appstart/task/MainInitTask.java",
    "chars": 1582,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/Product.java",
    "chars": 1852,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductFactory.java",
    "chars": 1383,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/entity/ProductInfo.java",
    "chars": 1765,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/AbstractProcessor.java",
    "chars": 2370,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GetProductInfoProcessor.java",
    "chars": 1506,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/GivePriceProcessor.java",
    "chars": 1499,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/PublicProductProcessor.java",
    "chars": 1697,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/processor/SearchFactoryProcessor.java",
    "chars": 1653,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/AbstractTask.java",
    "chars": 1283,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GetProductInfoTask.java",
    "chars": 2120,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/GivePriceTask.java",
    "chars": 1986,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/ProductTaskConstants.java",
    "chars": 989,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/PublicProductTask.java",
    "chars": 1992,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/business/task/SearchFactoryTask.java",
    "chars": 2424,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/BriefInfo.java",
    "chars": 2582,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/FactoryInfo.java",
    "chars": 2057,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PriceInfo.java",
    "chars": 2068,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/Product.java",
    "chars": 2119,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/PromotionInfo.java",
    "chars": 2325,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/entity/RichInfo.java",
    "chars": 1983,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetBriefInfoProcessor.java",
    "chars": 1839,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetFactoryInfoProcessor.java",
    "chars": 1777,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPriceInfoProcessor.java",
    "chars": 1707,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetPromotionInfoProcessor.java",
    "chars": 1810,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/processor/GetRichInfoProcessor.java",
    "chars": 1824,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetBriefInfoTask.java",
    "chars": 2414,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetFactoryInfoTask.java",
    "chars": 2672,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetPriceInfoTask.java",
    "chars": 2646,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetPromotionInfoTask.java",
    "chars": 2698,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/fragment/usecase/concurrent/task/GetRichInfoTask.java",
    "chars": 2635,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/utils/XToastUtils.java",
    "chars": 4352,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/utils/sdkinit/UMengInit.java",
    "chars": 3191,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/utils/sdkinit/XBasicLibInit.java",
    "chars": 2955,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/java/com/xuexiang/xtaskdemo/utils/service/JsonSerializationService.java",
    "chars": 1645,
    "preview": "/*\n * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1880,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "app/src/main/res/layout/adapter_item_simple_list_2.xml",
    "chars": 1449,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed unde"
  },
  {
    "path": "app/src/main/res/layout/fragment_usecase_compare.xml",
    "chars": 1953,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed unde"
  },
  {
    "path": "app/src/main/res/layout/fragment_usecase_template.xml",
    "chars": 1743,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed unde"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "chars": 875,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <color name=\"color"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 72,
    "preview": "<resources>\n    <string name=\"app_name\">XTaskDemo</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "chars": 1422,
    "preview": "<resources>\n\n    <!-- 拓展主题 theme. -->\n    <style name=\"XUITheme\" parent=\"XUIBaseTheme\">\n        <!--设置默认窗口的动画样式-->\n     "
  },
  {
    "path": "app/src/main/res/values/styles_widget.xml",
    "chars": 1170,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed unde"
  },
  {
    "path": "app/src/test/java/com/xuexiang/xtaskdemo/ExampleUnitTest.java",
    "chars": 395,
    "preview": "package com.xuexiang.xtaskdemo;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Example lo"
  },
  {
    "path": "app/x-library-simple.gradle",
    "chars": 1853,
    "preview": "//引用XAOP插件\napply plugin: 'com.xuexiang.xaop'\n//引用XRouter-plugin插件实现自动注册\napply plugin: 'com.xuexiang.xrouter'\n//引用aspectj"
  },
  {
    "path": "art/xtask.mdj",
    "chars": 249304,
    "preview": "{\n\t\"_type\": \"Project\",\n\t\"_id\": \"AAAAAAFF+h6SjaM2Hec=\",\n\t\"name\": \"Untitled\",\n\t\"ownedElements\": [\n\t\t{\n\t\t\t\"_type\": \"UMLMode"
  },
  {
    "path": "build.gradle",
    "chars": 899,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    a"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Fri Jun 28 16:23:16 CST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 978,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "settings.gradle",
    "chars": 61,
    "preview": "include ':app'\ninclude ':xtask-thread'\ninclude ':xtask-core'\n"
  },
  {
    "path": "versions.gradle",
    "chars": 8425,
    "preview": "import java.util.regex.Matcher\nimport java.util.regex.Pattern\n\next.deps = [:]\ndef versions = [:]\n\nversions.android_gradl"
  },
  {
    "path": "xtask-core/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "xtask-core/build.gradle",
    "chars": 435,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion build_versions.target_sdk\n    buildToolsVersion bui"
  },
  {
    "path": "xtask-core/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "xtask-core/src/main/AndroidManifest.xml",
    "chars": 686,
    "preview": "<!--\n  ~ Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/XTask.java",
    "chars": 11795,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/api/TaskChainEngine.java",
    "chars": 10693,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/api/step/ConcurrentGroupTaskStep.java",
    "chars": 3462,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/api/step/SerialGroupTaskStep.java",
    "chars": 3537,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/api/step/SimpleTaskStep.java",
    "chars": 2713,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/api/step/XTaskStep.java",
    "chars": 6820,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/ITaskChainCallback.java",
    "chars": 1592,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/ITaskChainEngine.java",
    "chars": 1910,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/ThreadType.java",
    "chars": 1080,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/IDataStore.java",
    "chars": 2570,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/ITaskParam.java",
    "chars": 1715,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/ITaskResult.java",
    "chars": 1881,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/MapDataStore.java",
    "chars": 2948,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/TaskParam.java",
    "chars": 4794,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/param/impl/TaskResult.java",
    "chars": 4074,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/IGroupTaskStep.java",
    "chars": 1135,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStep.java",
    "chars": 2523,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepController.java",
    "chars": 1407,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepHandler.java",
    "chars": 1683,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/ITaskStepLifecycle.java",
    "chars": 1219,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AbstractGroupTaskStep.java",
    "chars": 5547,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AbstractTaskStep.java",
    "chars": 9035,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AutoDestroyTaskChainCallback.java",
    "chars": 1555,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/AutoNotifyTaskStepHandler.java",
    "chars": 1825,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/TaskChainCallbackAdapter.java",
    "chars": 1415,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/core/step/impl/TaskCommand.java",
    "chars": 2972,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/utils/CancellerPoolUtils.java",
    "chars": 2633,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/utils/CommonUtils.java",
    "chars": 3013,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-core/src/main/java/com/xuexiang/xtask/utils/TaskUtils.java",
    "chars": 3743,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "xtask-thread/build.gradle",
    "chars": 401,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion build_versions.target_sdk\n    buildToolsVersion bui"
  },
  {
    "path": "xtask-thread/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "xtask-thread/src/main/AndroidManifest.xml",
    "chars": 693,
    "preview": "<!--\n  ~ Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/logger/ILogger.java",
    "chars": 973,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/logger/LogcatLogger.java",
    "chars": 3652,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/logger/TaskLogger.java",
    "chars": 8254,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/XTaskExecutor.java",
    "chars": 5492,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/ICategoryExecutorCore.java",
    "chars": 1924,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IExecutorCore.java",
    "chars": 826,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IPriorityExecutorCore.java",
    "chars": 1256,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/IScheduledExecutorCore.java",
    "chars": 1729,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/CategoryExecutorCore.java",
    "chars": 7890,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/PriorityExecutorCore.java",
    "chars": 3527,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/executor/impl/ScheduledExecutorCore.java",
    "chars": 2236,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/DefaultScheduledThreadPoolExecutor.java",
    "chars": 6319,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/DefaultThreadPoolExecutor.java",
    "chars": 7628,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/PriorityThreadPoolExecutor.java",
    "chars": 11621,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/TaskRecordPolicy.java",
    "chars": 1290,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/TaskThreadFactory.java",
    "chars": 4002,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/base/BaseScheduledThreadPoolExecutor.java",
    "chars": 3966,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/base/BaseThreadPoolExecutor.java",
    "chars": 5697,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/CancelHandlerRunnable.java",
    "chars": 2510,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICancelable.java",
    "chars": 914,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICanceller.java",
    "chars": 872,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/ICancellerPool.java",
    "chars": 1592,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/IFuture.java",
    "chars": 852,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/IScheduledFuture.java",
    "chars": 912,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/pool/cancel/TaskCancellerPool.java",
    "chars": 2340,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriority.java",
    "chars": 1110,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityCallable.java",
    "chars": 886,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityComparable.java",
    "chars": 832,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityFuture.java",
    "chars": 897,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityRunnable.java",
    "chars": 841,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/IPriorityStrategy.java",
    "chars": 983,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityCallable.java",
    "chars": 2328,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityFuture.java",
    "chars": 2474,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityRunnable.java",
    "chars": 2233,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/DefaultPriorityStrategy.java",
    "chars": 1403,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/priority/impl/Priority.java",
    "chars": 1551,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/CancelUtils.java",
    "chars": 1848,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/ExecutorUtils.java",
    "chars": 1726,
    "preview": "/*\n * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "xtask-thread/src/main/java/com/xuexiang/xtask/thread/utils/PriorityUtils.java",
    "chars": 2428,
    "preview": "/*\n * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the xuexiangjys/XTask GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 173 files (698.9 KB), approximately 211.9k tokens, and a symbol index with 1086 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!