-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSabianAsyncTask.java
More file actions
197 lines (165 loc) · 4.73 KB
/
SabianAsyncTask.java
File metadata and controls
197 lines (165 loc) · 4.73 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package com.sabiantools.utilities.threads;
import android.os.Handler;
import android.os.Looper;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Utility thread tool for multithreading. Alternative to {@link android.os.AsyncTask}
*/
public class SabianAsyncTask {
/**
* The single thread executor
*/
public static final String SERVICE_TYPE_SINGLE = "single";
/**
* Our executor
*/
private ExecutorService executor;
/**
* Our handler
*/
private Handler handler;
/**
* The service collections
*/
private HashMap<String, ExecutorService> services;
/**
* The current service to be used
* See {@link SabianAsyncTask#SERVICE_TYPE_SINGLE}
*/
private String service = SERVICE_TYPE_SINGLE;
/**
* Whether to cancel all tasks once they're finished
*/
private boolean awaitAllTasksToFinishBeforeCancel = false;
/**
* The time it will take for all tasks to complete before force shutting down in millisconds
*/
private int taskCancelDelay = 500;
/**
* Init all services
*/
public SabianAsyncTask() {
initServices();
initExecutor();
}
/**
* Inits the executor
*/
private void initExecutor() {
if (executor == null) {
executor = services.get(service);
}
}
/**
* Inits the handler
*/
private void initHandler() {
if (handler == null) {
handler = new Handler(Looper.getMainLooper());
}
}
/**
* Inits all the services
*/
private void initServices() {
if (services != null)
return;
services = new HashMap<>();
services.put(SERVICE_TYPE_SINGLE, Executors.newSingleThreadExecutor());
}
/**
* Registers a new service to the thread pool collection
*
* @param name
* @param service
* @return
*/
public SabianAsyncTask registerService(String name, ExecutorService service) {
this.services.put(name, service);
return this;
}
/**
* Sets the default thread service to be used
* See {@link SabianAsyncTask#SERVICE_TYPE_SINGLE}
* You can register a custom one using {@link SabianAsyncTask#registerService(String, ExecutorService)}
*
* @param service
* @return
*/
public SabianAsyncTask setService(String service) {
this.service = service;
executor = services.get(service);
return this;
}
/**
* Executes a background task
*
* @param callable
* @param callback
* @param <R>
*/
public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
initExecutor();
callback.onBefore();
executor.execute(() -> {
R result = null;
Throwable throwable = null;
try {
result = callable.call();
} catch (Exception e) {
throwable = e;
}
boolean isSuccess = throwable == null;
R finalResult = result;
Throwable error = throwable;
initHandler();
handler.post(() -> {
if (isSuccess)
callback.onComplete(finalResult);
else {
callback.onError(error);
}
});
});
}
/**
* Cancels running background tasks if any
*/
public void cancel() {
try {
if (executor != null) {
// Stop accepting new tasks
executor.shutdown();
// Attempt to shut down left tasks if any
try {
//Shut down all tasks immediately
if (!awaitAllTasksToFinishBeforeCancel) {
executor.shutdown();
} else {
// Wait a while for existing tasks to terminate
if (!executor.awaitTermination(taskCancelDelay, TimeUnit.MILLISECONDS)) {
//Terminate all pending running tasks
executor.shutdownNow();
}
}
} catch (Exception e) {
executor.shutdownNow();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
}
if (executor != null) {
executor = null;
}
}
}
}