You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Dec 17, 2020. It is now read-only.
>This library is useful if you need to do stuff in the background which is heavily bound to the user-interface, like: Refreshing large lists from a database, loading an article from a network source or decoding an image. You need to use an additional library if you need: task scheduling, automatic retries, task persistence across reboots, task constrains (network availability) etc.
29
+
30
+
31
+
22
32
23
33
## 1. Basic usage
24
34
---
25
35
In order to, execute a task which modifies the user-interface and to retain it across configuration changes you will need to do three things:
26
36
27
37
1. Create an implementation of the `Task` class;
28
-
2.Execute the task using the `TaskManager` in an`Activity` which implements the `Callback` interface;
29
-
3.Retain the task when configuration changes by overriding the `onStart()` method and calling the `TaskManager.attachListener()` method;
38
+
2.Make your Activity extend the `TaskActivity` class (or for Fragments the `TaskFragment` class);
39
+
3.Implement the `Callback` interface somewhere and execute the task using the `TaskManager`;
30
40
31
-
The Activity's `TaskManager` makes sure that tasks can be retained across configuration changes and is responsible for removing the `Callback` listener when the Activity's user-interface is no longer valid. You are however responsible for re-attaching a new `Callback` listener when the Activity 's user-interface is restarted.
Before you can execute the `ExampleTask` you first need to get the current Activity's `TaskManager`. A `TaskManager` keeps references to tasks and executes them. You can obtain the current Activity's `TaskManager` using the `TaskManager.getActivityTaskManager()` method:
71
+
### 1.2 Extending from the TaskActivity class
72
+
The `TaskActivity` class is the most easy way to use this library, make sure your Activity extends from it and it wil take care of retaining all `Tasks` started by the Activity's `TaskManager`.
Then you can execute the task using the `TaskManager.execute()` method. This method needs two arguments, the task to execute and a `Callback` listener to send feedback to. Preferably your activity implements the `Callback` interface, but this isn't necessarily needed.
80
+
>**Help, I already extend some custom Activity implementation!**
81
+
>Don't worry, you can easily add the `TaskActivity` behaviour to any Activity or Fragment by using the `TaskManagerLifeCycleProxy` class . Check out [this sample](#using-the-taskmanagerlifecycleproxy-to-mimic-the-taskactivity).
82
+
83
+
### 1.3 Execute the Task and receive callback
84
+
Before you can execute the `ExampleTask` you first need to get the current Activity's `TaskManager`. A `TaskManager` keeps references to tasks and executes them. You can obtain the current Activity's `TaskManager` using the `TaskActivity.getTaskManager()` method.
85
+
86
+
Then you can execute the task using the `TaskManager.execute()` method. This method needs two arguments, the task to execute and a `Callback` listener to send feedback to. Preferably your activity implements the `Callback` interface, but this isn't necessarily needed. The `TaskManager` currently always executes tasks in parallel *(work in progress to make it a option)*.
@@ -93,43 +108,57 @@ public class Main extends AppCompatActivity implements Task.Callback {
93
108
}
94
109
```
95
110
96
-
### 1.2 Retaining the task
97
-
When the configuration changes (device rotates) the Activity's `TaskManager` will automatically remove the `Callback` listeners from all active tasks. This is needed otherwise the tasks could leak Activity, Fragment or other references.
98
111
99
-
> **In-depth:**
100
-
> The `TaskManager` will automatically remove the `Callback` listeners when the Activity is stopping (`onStop()`). At this moment the user-interface has become *"unstable"*, for example, when this happens the FragmentManager refuses to add new Fragments because the Activity's `onSaveInstanceState()` method has already been called. If the `Callback` listener is not removed by the `TaskManager` before this point, then a `DialogFragment.show()` call will throw an exception when called in the `onPostExecute()` method. This is why the `Callback` listeners are removed when the Activity stops.
112
+
>**Tip:**
113
+
>You can also make your Fragment extend the `TaskFragment` class and use a Fragment to execute and retain your task in. It works exactly the same, but keep in mind that the `Callback` listeners are removed as soon as the Fragments stops (`onStop()`).
114
+
101
115
102
-
To retain the task when your Activity is recreated you will need to re-attach a (new) `Callback` listener using the `TaskManager.attachListener()` method. The best place to do this is in the `onStart()` method right after the user-interface has been created.
116
+
### 1.4 Retaining the task
117
+
When the configuration changes (device rotates) the `TaskManager` will automatically remove the `Callback` listeners from all active tasks and retain all `Tasks`. Removing the `Callback` is needed otherwise the tasks could leak Activity, Fragment or other references.
103
118
119
+
> **In-depth:**
120
+
> The `TaskManger` (or actually a internal class) will detect when the Activity stops (`onStop()`). and will automatically remove all `Callback` listeners when this happens. At this moment the user-interface has become *"unstable"*, this means that some user-interface functionality stops working. For example, the `FragmentManager` refuses at this point to add new Fragments because the Activity's `onSaveInstanceState()` method already has been called. If the `Callback` listener is not removed by the `TaskManager` before this point, then a `DialogFragment.show()` call will throw an exception when called in the `onPostExecute()` method. This is why the `Callback` listeners are removed when the Activity stops.
121
+
122
+
Although tasks are automatically retained, you will still need to provide a new `Callback` listener for each `Task`. You can easily do this by implementing (overriding) the `TaskActivity` (or `TaskFragment`) `onPreAttachTask(Task)` method and return a `Callback` instance. At this point you can also use the `onPreAttachTask(Task)` method to restore the user-interface state according to the `Tasks` state. The `onPreAttachTask(Task)` method will be called for each task that isn't finished (didn't deliver).
104
123
105
124
```java
106
-
@Override
107
-
publicvoid onStart(){
108
-
super.onStart();
109
-
//Re-attach the this Activity as listener for task
Tasks retained using the described method are stored in a *"no-ui-fragment"* this fragment retained across configuration changes and is added to your Activity's `FragmentManager` the first time you call `TaskManager.getActivityTaskManager()`. This fragment is from that point on bound to the Activity's life-cycle and holds an internal `TaskManager`. The fragment makes sure that the internal `TaskManager` removes all `Callback` listeners as soon as the Activity is stopping (`onStop()`).
138
+
####**How are tasks retained?**
139
+
Tasks are are stored in `FragmentManagers` which are stored in a *"no-ui-fragment"* this fragment retained across configuration changes and is added to your Activity's `FragmentManager` the first time you call:
When a Task doesn't have a `Callback` listener to deliver it's results to it will skip the delivery and redeliver the results as soon as a new listener is attached. If you call the `TaskManager.attachListener()` method in the `onStart()` method, then the listener will be fired and you need to be sure that the user-interface is ready.
146
+
The *"no-ui-fragment"* is from that point on bound to the Activity's life-cycle and keeps track of all `TaskManager` instances. It also makes sure that all internal `TaskManagers` remove all `Callback` listeners as soon as the Activity is stopping (`onStop()`). It might also throw an exception if a `Fragment``TaskManger` did not remove the `Callback` listeners, so that you (the developer) know you've messed up.
121
147
122
-
Only the `onPostExecute()` and `onCanceled()` methods will be redelivered, other methodes won't be redelivered.
148
+
####**What happens when a Task without callback finishes?**
149
+
When a Task doesn't have a `Callback` listener to deliver it's results to it will skip the delivery and redeliver the results as soon as a new listener is attached. This happens for example when the `onPreAttachTask(Task)` method returns, the newly provided `Callback` listener will be fired and you need to be sure that the user-interface is ready. It might also happen if you manually call one of the `TaskManager.attach()` methods (advanced usage).
123
150
124
-
####**Task and Callback life-cycle**
125
-
A `Task` basically has four life-cycle methods:
151
+
**Important:** Only the `onPostExecute()` and `onCanceled()` methods will be redelivered, other methodes won't be redelivered. You can restore a tasks progress using the `Task.getLastKnownProgress()` method.
152
+
153
+
####**What does the Task and Callback life-cycle look like?**
154
+
A `Task` basically has four life-cycle methods *(its heavily based on Android's AsyncTask)*:
126
155
127
156
*`onPreExecute()`*[ui-thread]*
128
157
*`doInBackground()`*[executor-thread]*
129
158
*`onProgressUpdate()`*[ui-thread]*
130
159
*`onPostExecute()` or `onCanceled()`*[ui-thread]*
131
160
132
-
A `Callback` listener has the same life-cycle methods as the`Task` and reflects those methods to, for example, an Activity. All `Callback` methods are executed on the user interface thread. When a `Callback` listener is attached to the task, both the `Callback` and the `Task` methods will be called. But when the listener is detached from the task only the tasks methods will be called. With the exception of the `onPostExecute()` and `onCanceled()` methods which can be redelivered.
161
+
A `Callback` listener has the same life-cycle methods as the`Task`. All `Callback` methods are executed on the user interface thread. When a `Callback` listener is attached to the task, both the `Callback` and the `Task` methods will be called. But when the listener is detached from the task only the tasks methods will be called. With exception of the `onPostExecute()` and `onCanceled()` methods which can be redelivered.
133
162
134
163
135
164
## 3. Advanced usage
@@ -155,7 +184,7 @@ To get the tasks most recent progress update use the `getLastKnownProgress()` me
155
184
If you need the `onProgressUpdated` and `onCanceled` callback methods you can implement the `AdvancedCallback` interface, which is an extension of the `Callback` interface.
156
185
157
186
####**TaskExecutor & Executor**
158
-
You can also execute tasks without using a `TaskManager` this means that you are responsible for removing and setting the `Callback` listener. Executing tasks without using the `TaskManager` is handy when you don't need to get any feedback to the Activity's user-interface.
187
+
You can also execute tasks without using a `TaskManager` this means that you are responsible for removing and setting the `Callback` listener. Executing tasks without using the `TaskManager` is handy when you don't perse need to get any feedback to the user-interface.
159
188
160
189
```java
161
190
TaskExecutor.executeParallel(newExampleTask());
@@ -174,32 +203,86 @@ You can also use a custom java `Executor` to execute tasks with:
####**Using the TaskManagerLifeCycleProxy to mimic the TaskActivity**
207
+
If you already use some custom Activity or Fragment implementation you might not be able to use the `TaskActivity` or `TaskFragment` class. To overcome this problem you can implement the behaviour of the `TaskActivity` yourself using the `TaskManagerLifeCycleProxy` class.
208
+
209
+
Create a new `TaskManagerLifeCycleProxy` instance and let your Activity (or Fragment) implement the `TaskManagerProvider` interface. Override the`onStart()` and `onStop()` methods and proxy those together with the `getTaskManager()` method to the `TaskManagerLifeCycleProxy` instance.
####**Why does the Task class still have the onPostExecute and onPreExecute etc. methods?**
180
247
181
-
Although the `Callback` interface provides these methods sometimes you don't need any callback to the Activity's user-interface, at that moment the Task methods come in handy.
248
+
Although the `Callback` interface provides these methods sometimes you don't need any callback to the Activity's user-interface, at that moment the Task methods come in handy. It also gives a `Task` the change to modify it's state or store it's progress values, for example:
0 commit comments