├── .gitignore
├── AsyncJob
├── AsyncJob.iml
├── build.gradle
├── gradle.properties
├── maven_push.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── arasthel
│ └── asyncjob
│ └── AsyncJob.java
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
--------------------------------------------------------------------------------
/AsyncJob/AsyncJob.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/AsyncJob/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 21
5 | buildToolsVersion "21.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 8
9 | targetSdkVersion 21
10 | versionCode 1
11 | versionName "1.0.3"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | }
24 |
25 | allprojects {
26 | version = VERSION_NAME
27 | group = GROUP
28 |
29 | repositories {
30 | mavenCentral()
31 | }
32 | }
33 |
34 | // Script to upload plugin to Maven
35 | apply from: './maven_push.gradle'
36 |
--------------------------------------------------------------------------------
/AsyncJob/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=AsyncJobLibrary
2 | POM_ARTIFACT_ID=asyncjob-library
3 | POM_PACKAGING=aar
--------------------------------------------------------------------------------
/AsyncJob/maven_push.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'signing'
3 |
4 | def sonatypeRepositoryUrl
5 | if (isReleaseBuild()) {
6 | println 'RELEASE BUILD'
7 | sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
8 | } else {
9 | println 'DEBUG BUILD'
10 | sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
11 | }
12 |
13 | def getRepositoryUsername() {
14 | return hasProperty('nexusUsername') ? nexusUsername : ""
15 | }
16 |
17 | def getRepositoryPassword() {
18 | return hasProperty('nexusPassword') ? nexusPassword : ""
19 | }
20 |
21 | def isReleaseBuild() {
22 | return version.contains("SNAPSHOT") == false
23 | }
24 |
25 | afterEvaluate { project ->
26 | uploadArchives {
27 | repositories {
28 | mavenDeployer {
29 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
30 |
31 | pom.artifactId = POM_ARTIFACT_ID
32 |
33 | repository(url: sonatypeRepositoryUrl) {
34 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
35 | }
36 |
37 | pom.project {
38 | name POM_NAME
39 | packaging POM_PACKAGING
40 | description POM_DESCRIPTION
41 | url POM_URL
42 |
43 | scm {
44 | url POM_SCM_URL
45 | connection POM_SCM_CONNECTION
46 | developerConnection POM_SCM_DEV_CONNECTION
47 | }
48 |
49 | licenses {
50 | license {
51 | name POM_LICENCE_NAME
52 | url POM_LICENCE_URL
53 | distribution POM_LICENCE_DIST
54 | }
55 | }
56 |
57 | developers {
58 | developer {
59 | id POM_DEVELOPER_ID
60 | name POM_DEVELOPER_NAME
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | signing {
69 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
70 | sign configurations.archives
71 | }
72 |
73 | task androidJavadocs(type: Javadoc) {
74 | //source = android.sourceSets.main.allJava
75 | }
76 |
77 | task androidJavadocsJar(type: Jar) {
78 | classifier = 'javadoc'
79 | //basename = artifact_id
80 | from androidJavadocs.destinationDir
81 | }
82 |
83 | task androidSourcesJar(type: Jar) {
84 | classifier = 'sources'
85 | //basename = artifact_id
86 | //from android.sourceSets.main.allSource
87 | }
88 |
89 | artifacts {
90 | //archives packageReleaseJar
91 | archives androidSourcesJar
92 | archives androidJavadocsJar
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/AsyncJob/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/AsyncJob/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AsyncJob/src/main/java/com/arasthel/asyncjob/AsyncJob.java:
--------------------------------------------------------------------------------
1 | package com.arasthel.asyncjob;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | import java.util.concurrent.ExecutorService;
7 | import java.util.concurrent.FutureTask;
8 |
9 | /**
10 | * Created by Arasthel on 08/07/14.
11 | */
12 | public class AsyncJob {
13 |
14 | private static Handler uiHandler = new Handler(Looper.getMainLooper());
15 |
16 | // Action to do in background
17 | private AsyncAction actionInBackground;
18 | // Action to do when the background action ends
19 | private AsyncResultAction actionOnMainThread;
20 |
21 | // An optional ExecutorService to enqueue the actions
22 | private ExecutorService executorService;
23 |
24 | // The thread created for the action
25 | private Thread asyncThread;
26 | // The FutureTask created for the action
27 | private FutureTask asyncFutureTask;
28 |
29 | // The result of the background action
30 | private JobResult result;
31 |
32 | /**
33 | * Instantiates a new AsyncJob
34 | */
35 | public AsyncJob() {
36 | }
37 |
38 | /**
39 | * Executes the provided code immediately on the UI Thread
40 | * @param onMainThreadJob Interface that wraps the code to execute
41 | */
42 | public static void doOnMainThread(final OnMainThreadJob onMainThreadJob) {
43 | uiHandler.post(new Runnable() {
44 | @Override
45 | public void run() {
46 | onMainThreadJob.doInUIThread();
47 | }
48 | });
49 | }
50 |
51 | /**
52 | * Executes the provided code immediately on a background thread
53 | * @param onBackgroundJob Interface that wraps the code to execute
54 | */
55 | public static void doInBackground(final OnBackgroundJob onBackgroundJob) {
56 | new Thread(new Runnable() {
57 | @Override
58 | public void run() {
59 | onBackgroundJob.doOnBackground();
60 | }
61 | }).start();
62 | }
63 |
64 | /**
65 | * Executes the provided code immediately on a background thread that will be submitted to the
66 | * provided ExecutorService
67 | * @param onBackgroundJob Interface that wraps the code to execute
68 | * @param executor Will queue the provided code
69 | */
70 | public static FutureTask doInBackground(final OnBackgroundJob onBackgroundJob, ExecutorService executor) {
71 | FutureTask task = (FutureTask) executor.submit(new Runnable() {
72 | @Override
73 | public void run() {
74 | onBackgroundJob.doOnBackground();
75 | }
76 | });
77 |
78 | return task;
79 | }
80 |
81 | /**
82 | * Begins the background execution providing a result, similar to an AsyncTask.
83 | * It will execute it on a new Thread or using the provided ExecutorService
84 | */
85 | public void start() {
86 | if(actionInBackground != null) {
87 |
88 | Runnable jobToRun = new Runnable() {
89 | @Override
90 | public void run() {
91 | result = (JobResult) actionInBackground.doAsync();
92 | onResult();
93 | }
94 | };
95 |
96 | if(getExecutorService() != null) {
97 | asyncFutureTask = (FutureTask) getExecutorService().submit(jobToRun);
98 | } else {
99 | asyncThread = new Thread(jobToRun);
100 | asyncThread.start();
101 | }
102 | }
103 | }
104 |
105 | /**
106 | * Cancels the AsyncJob interrupting the inner thread.
107 | */
108 | public void cancel() {
109 | if(actionInBackground != null) {
110 | if(executorService != null) {
111 | asyncFutureTask.cancel(true);
112 | } else {
113 | asyncThread.interrupt();
114 | }
115 | }
116 | }
117 |
118 |
119 | private void onResult() {
120 | if (actionOnMainThread != null) {
121 | uiHandler.post(new Runnable() {
122 | @Override
123 | public void run() {
124 | actionOnMainThread.onResult(result);
125 | }
126 | });
127 | }
128 | }
129 |
130 | public ExecutorService getExecutorService() {
131 | return executorService;
132 | }
133 |
134 | public void setExecutorService(ExecutorService executorService) {
135 | this.executorService = executorService;
136 | }
137 |
138 | public AsyncAction getActionInBackground() {
139 | return actionInBackground;
140 | }
141 |
142 | /**
143 | * Specifies which action to run in background
144 | * @param actionInBackground the action
145 | */
146 | public void setActionInBackground(AsyncAction actionInBackground) {
147 | this.actionInBackground = actionInBackground;
148 | }
149 |
150 | public AsyncResultAction getActionOnResult() {
151 | return actionOnMainThread;
152 | }
153 |
154 | /**
155 | * Specifies which action to run when the background action is finished
156 | * @param actionOnMainThread the action
157 | */
158 | public void setActionOnResult(AsyncResultAction actionOnMainThread) {
159 | this.actionOnMainThread = actionOnMainThread;
160 | }
161 |
162 | public interface AsyncAction {
163 | public ActionResult doAsync();
164 | }
165 |
166 | public interface AsyncResultAction {
167 | public void onResult(ActionResult result);
168 | }
169 |
170 | public interface OnMainThreadJob {
171 | public void doInUIThread();
172 | }
173 |
174 | public interface OnBackgroundJob {
175 | public void doOnBackground();
176 | }
177 |
178 | /**
179 | * Builder class to instantiate an AsyncJob in a clean way
180 | * @param the type of the expected result
181 | */
182 | public static class AsyncJobBuilder {
183 |
184 | private AsyncAction asyncAction;
185 | private AsyncResultAction asyncResultAction;
186 | private ExecutorService executor;
187 |
188 | public AsyncJobBuilder() {
189 |
190 | }
191 |
192 | /**
193 | * Specifies which action to run on background
194 | * @param action the AsyncAction to run
195 | * @return the builder object
196 | */
197 | public AsyncJobBuilder doInBackground(AsyncAction action) {
198 | asyncAction = action;
199 | return this;
200 | }
201 |
202 | /**
203 | * Specifies which action to run when the background action ends
204 | * @param action the AsyncAction to run
205 | * @return the builder object
206 | */
207 | public AsyncJobBuilder doWhenFinished(AsyncResultAction action) {
208 | asyncResultAction = action;
209 | return this;
210 | }
211 |
212 | /**
213 | * Used to provide an ExecutorService to launch the AsyncActions
214 | * @param executor the ExecutorService which will queue the actions
215 | * @return the builder object
216 | */
217 | public AsyncJobBuilder withExecutor(ExecutorService executor) {
218 | this.executor = executor;
219 | return this;
220 | }
221 |
222 | /**
223 | * Instantiates a new AsyncJob of the given type
224 | * @return a configured AsyncJob instance
225 | */
226 | public AsyncJob create() {
227 | AsyncJob asyncJob = new AsyncJob();
228 | asyncJob.setActionInBackground(asyncAction);
229 | asyncJob.setActionOnResult(asyncResultAction);
230 | asyncJob.setExecutorService(executor);
231 | return asyncJob;
232 | }
233 |
234 | }
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2014 Jorge Martín Espinosa (Arasthel)
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AsyncJobLibrary
2 | ===============
3 |
4 | Android library to easily queue background and UI tasks
5 |
6 | ## Index
7 | * [Why AsyncJob?](#why-asyncjob)
8 | * [So what does it exactly do?](#so-what-does-it-exactly-do)
9 | * [How does it work?](#how-does-it-work)
10 | * [Using static methods](#using-static-methods)
11 | * [Threading with ExecutorServices](#thats-good-but-id-like-to-have-a-better-control-of-my-background-threads)
12 | * [How do I add it to my project?](#how-do-i-add-it-to-my-project)
13 | * [Reference](#reference)
14 | * [Interfaces](#interfaces)
15 | * [AsyncJob static methods](#asyncjob-static-methods)
16 | * [AsyncJob object methods](#asyncjob-object-methods)
17 | * [AsyncJobBuilder methods](#asyncjobbuilder-methods)
18 | * [License](#license)
19 | * [About me](#about-me)
20 |
21 | ## Why AsyncJob?
22 |
23 | In my latest projects I started using [Android Annotations](http://androidannotations.org/), which has an amazing set of tools to make creating Android applications a lot easier.
24 |
25 | However, for some stuff I wanted to make having to inherit from auto-built classes was an impossible thing to do and I ended up having half of my project using *AndroidAnnotations* and the other half doing stuff manually.
26 |
27 | So I thought: maybe I should try [ButterKnife](http://jakewharton.github.io/butterknife/) instead. That worked better, I could inject views whenever I wanted and I still had some of the "@Click" stuff I liked.
28 |
29 | But not everything was good. *AndroidAnnotations* had a pair of annotations called **@Background** and **@UIThread** which magically -well, not so magically- allowed your code to be executed on the UI Thread or on a Background one with no effort. I *REALLY* missed those annotations as they allowed me to have a way cleaner code, so I started thinking how could I replace them.
30 |
31 | **AsyncJob** was the closest I got to that.
32 |
33 | ## So what does it exactly do?
34 |
35 | If you are working on Android you probably have ended up using AsyncTasks to do background tasks and then have a response on the UI Thread. Well, I'll confess: **I HATE ASYNCTASKS**.
36 |
37 | I don't see why I would need to extend a class *EVERY FUCKING TIME* I want to do some work on background. Also, having to create a Thread and a Handler *EVERY FUCKING TIME* I wanted to do some background work and have a response wasn't a good option.
38 |
39 | So what I did was to create a library which does that for you.
40 |
41 | ## How does it work?
42 |
43 | It's really easy. If you want the library to work in a similar way to *AsyncTask*, you can create an ``AsyncJob`` where **JobResult** is the type or class of the item it will return.
44 |
45 | But creating an **AsyncJob** was also a boring thing to do so I created an ``AsyncJobBuilder`` which allows you to create **AsyncJobs** in a fast and clean way.
46 |
47 | **AsyncJobs** have two interfaces which will be used to store your code and execute it on backgrund or on the main thread. These are
48 | ``AsyncAction`` and ``AsyncResultAction``. They can be set by:
49 |
50 | ```java
51 | asyncJob.setActionInBackground(actionInBackground);
52 | asyncJob.setActionOnResult(actionOnMainThread);
53 | ```
54 |
55 | And when you use ``asyncJob.start()`` it will call those interfaces and execute your code.
56 |
57 | Here you have an example of an **AsyncJob** created by an **AsyncJobBuilder**:
58 |
59 | ```java
60 | new AsyncJob.AsyncJobBuilder()
61 | .doInBackground(new AsyncJob.AsyncAction() {
62 | @Override
63 | public Boolean doAsync() {
64 | // Do some background work
65 | try {
66 | Thread.sleep(1000);
67 | } catch (InterruptedException e) {
68 | e.printStackTrace();
69 | }
70 | return true;
71 | }
72 | })
73 | .doWhenFinished(new AsyncJob.AsyncResultAction() {
74 | @Override
75 | public void onResult(Boolean result) {
76 | Toast.makeText(context, "Result was: " + result, Toast.LENGTH_SHORT).show();
77 | }
78 | }).create().start();
79 |
80 | ```
81 |
82 | ### Using static methods
83 |
84 | Most of the time, though, I will prefer doing the following:
85 |
86 | * Execute some code in background.
87 | * Execute some code on the UI thread from that background thread whenever I have to, not just to return a value.
88 |
89 | So how do yo do that?
90 |
91 | You use the provided static methods, ``AsyncJob.doInBackground()`` and ``AsyncJob.doOnMainThread()``:
92 |
93 | ```java
94 | AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
95 | @Override
96 | public void doOnBackground() {
97 |
98 | // Pretend it's doing some background processing
99 | try {
100 | Thread.sleep(1000);
101 | } catch (InterruptedException e) {
102 | e.printStackTrace();
103 | }
104 |
105 | // Create a fake result (MUST be final)
106 | final boolean result = true;
107 |
108 | // Send the result to the UI thread and show it on a Toast
109 | AsyncJob.doOnMainThread(new AsyncJob.OnMainThreadJob() {
110 | @Override
111 | public void doInUIThread() {
112 | Toast.makeText(context, "Result was: "+ result, Toast.LENGTH_SHORT).show();
113 | }
114 | });
115 | }
116 | });
117 |
118 | ```
119 |
120 | Which also have some interfaces made specially for them.
121 |
122 | ## That's good, but I'd like to have a better control of my background threads!
123 |
124 | Well, you can. You can provide an ```ExecutorService``` to an **AsyncJob** and the tasks that you want will be queued to it:
125 |
126 | ```java
127 | // Create a job to run on background
128 | AsyncJob.OnBackgroundJob job = new AsyncJob.OnBackgroundJob() {
129 | @Override
130 | public void doOnBackground() {
131 | // Pretend to do some background processing
132 | try {
133 | Thread.sleep(1000);
134 | } catch (InterruptedException e) {
135 | e.printStackTrace();
136 | }
137 |
138 | // This toast should show a difference of 1000ms between calls
139 | AsyncJob.doOnMainThread(new AsyncJob.OnMainThreadJob() {
140 | @Override
141 | public void doInUIThread() {
142 | Toast.makeText(context, "Finished on: "+System.currentTimeMillis(), Toast.LENGTH_SHORT).show();
143 | }
144 | });
145 | }
146 | };
147 |
148 | // This ExecutorService will run only a thread at a time
149 | ExecutorService executorService = Executors.newSingleThreadExecutor();
150 |
151 | // Send 5 jobs to queue which will be executed one at a time
152 | for(int i = 0; i < 5; i++) {
153 | AsyncJob.doInBackground(job, executorService);
154 | }
155 | ```
156 |
157 | In this example, I am supplying a SingleThreadExecutor to the AsyncJob, which will only allow **one** thread to run at a time, serializing their execution. You can provide any other ExecutorServices tof it your needs.
158 |
159 | ## How do I add it to my project?
160 |
161 | Add it to your gradle dependencies like this:
162 |
163 | ```groovy
164 | dependencies {
165 | ...
166 | compile 'com.arasthel:asyncjob-library:1.0.3'
167 | ...
168 | }
169 |
170 | ```
171 |
172 | Also, you can manually download or clone this repo and import it to your current project as a Module.
173 |
174 | ## Reference:
175 |
176 | #### Interfaces:
177 |
178 | ```java
179 | // These are for AsyncJob objects
180 | public interface AsyncAction {
181 | public ActionResult doAsync();
182 | }
183 | public interface AsyncResultAction {
184 | public void onResult(ActionResult result);
185 | }
186 |
187 | // These are for the static methods
188 | public interface OnMainThreadJob {
189 | public void doInUIThread();
190 | }
191 | public interface OnBackgroundJob {
192 | public void doOnBackground();
193 | }
194 |
195 | ```
196 |
197 | #### AsyncJob static methods:
198 |
199 | ```java
200 | /**
201 | * Executes the provided code immediately on a background thread
202 | * @param onBackgroundJob Interface that wraps the code to execute
203 | */
204 | public static void doInBackground(OnBackgroundJob onBackgroundJob);
205 |
206 | /**
207 | * Executes the provided code immediately on the UI Thread
208 | * @param onMainThreadJob Interface that wraps the code to execute
209 | */
210 | public static void doOnMainThread(final OnMainThreadJob onMainThreadJob);
211 |
212 | /**
213 | * Executes the provided code immediately on a background thread that will be submitted to the
214 | * provided ExecutorService
215 | * @param onBackgroundJob Interface that wraps the code to execute
216 | * @param executor Will queue the provided code
217 | */
218 | public static FutureTask doInBackground(final OnBackgroundJob onBackgroundJob, ExecutorService executor);
219 |
220 | ```
221 |
222 | #### AsyncJob object methods:
223 |
224 | ```java
225 | public AsyncJob();
226 | // Sets the action to execute on background
227 | public void setActionInBackground(AsyncAction actionInBackground);
228 | public AsyncAction getActionInBackground();
229 |
230 | // Sets an action to be executed when the background one ends and returns a result
231 | public void setActionOnResult(AsyncResultAction actionOnMainThread);
232 | public AsyncResultAction getActionOnResult();
233 |
234 | // Sets the optional ExecutorService to queue the jobs
235 | public void setExecutorService(ExecutorService executorService);
236 | public ExecutorService getExecutorService();
237 |
238 | // Cancels the AsyncJob interrupting the inner thread.
239 | public void cancel();
240 |
241 | // Starts the execution
242 | public void start();
243 |
244 | ```
245 |
246 | #### AsyncJobBuilder methods:
247 |
248 | ```java
249 | public AsyncJobBuilder();
250 |
251 | /**
252 | * Specifies which action to run on background
253 | * @param action the AsyncAction to run
254 | * @return the builder object
255 | */
256 | public AsyncJobBuilder doInBackground(AsyncAction action);
257 |
258 | /**
259 | * Specifies which action to run when the background action ends
260 | * @param action the AsyncAction to run
261 | * @return the builder object
262 | */
263 | public AsyncJobBuilder doWhenFinished(AsyncResultAction action);
264 |
265 | /**
266 | * Used to provide an ExecutorService to launch the AsyncActions
267 | * @param executor the ExecutorService which will queue the actions
268 | * @return the builder object
269 | */
270 | public AsyncJobBuilder withExecutor(ExecutorService executor);
271 |
272 | /**
273 | * Instantiates a new AsyncJob of the given type
274 | * @return a configured AsyncJob instance
275 | */
276 | public AsyncJob create();
277 |
278 | ```
279 |
280 | ## License
281 |
282 | This software is licensed under Apachev2 which basically means that you can make your own version and it can be private.
283 |
284 | Here is a small summary of the license:
285 |
286 | ```
287 | Copyright 2014 Jorge Martín Espinosa (Arasthel)
288 |
289 | Licensed under the Apache License, Version 2.0 (the "License");
290 | you may not use this file except in compliance with the License.
291 | You may obtain a copy of the License at
292 |
293 | http://www.apache.org/licenses/LICENSE-2.0
294 |
295 | Unless required by applicable law or agreed to in writing, software
296 | distributed under the License is distributed on an "AS IS" BASIS,
297 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
298 | See the License for the specific language governing permissions and
299 | limitations under the License.
300 |
301 | ```
302 |
303 | ## About me:
304 |
305 | I'm a freelance Android developer which can also code some Objective-C, Swift and little web (RoR, Django, even some NodeJS...). You can find more about me here. Bad thing is: I'm Spanish and I mostly speak Spanish on those sites. Anyway, you can contact me writing in English if you need help or want to talk.
306 |
307 | [](https://twitter.com/arasthel92) [](https://www.linkedin.com/profile/view?id=168652113)
308 | [](http://blog.arasthel.com)
309 |
--------------------------------------------------------------------------------