Skip to content
This repository was archived by the owner on Dec 17, 2020. It is now read-only.

Commit 7c3e2f8

Browse files
committed
- Added a strict mode debug option;
- Renamed the TaskActivity and TaskFragment to TaskActivityCompat and TaskFragmentCompat; - Added a android.app.Activity TaskActivity and android.app.Fragment TaskFragment for use on API 11+; - Minor bug fixes;
1 parent 40d94b8 commit 7c3e2f8

File tree

18 files changed

+319
-48
lines changed

18 files changed

+319
-48
lines changed

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies {
3737
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:
3838

3939
1. Create an implementation of the `Task` class;
40-
2. Make your Activity extend the `TaskActivity` class (or for Fragments the `TaskFragment` class);
40+
2. Make your Activity extend the `TaskActivityCompat` class (or for Fragments the `TaskFragmentCompat` class);
4141
3. Implement the `Callback` interface somewhere and execute the task using the `TaskManager`;
4242

4343

@@ -70,20 +70,20 @@ private class ExampleTask extends Task<Integer, String> {
7070
}
7171
```
7272

73-
### 1.2 Extending from the TaskActivity class
74-
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`.
73+
### 1.2 Extending from the TaskActivityCompat class
74+
The `TaskActivityCompat` 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`.
7575

7676
```java
77-
public class Main extends TaskActivity {
77+
public class Main extends TaskActivityCompat {
7878

7979
}
8080
```
8181

8282
>**Help, I already extend some custom Activity implementation!**
83-
>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).
83+
>Don't worry, you can easily add the `TaskActivityCompat` behaviour to any Activity or Fragment by using the `TaskManagerLifeCycleProxy` class . Check out [this sample](#using-the-taskmanagerlifecycleproxy-to-mimic-the-taskactivity).
8484
8585
### 1.3 Execute the Task and receive callback
86-
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.
86+
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 `TaskActivityCompat.getTaskManager()` method.
8787

8888
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)*.
8989

@@ -112,7 +112,7 @@ public class Main extends AppCompatActivity implements Task.Callback {
112112

113113

114114
>**Tip:**
115-
>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()`).
115+
>You can also make your Fragment extend the `TaskFragmentCompat` 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()`).
116116
117117

118118
### 1.4 Retaining the task
@@ -121,7 +121,7 @@ When the configuration changes (device rotates) the `TaskManager` will automatic
121121
> **In-depth:**
122122
> 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.
123123
124-
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).
124+
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 `TaskActivityCompat` (or `TaskFragmentCompat`) `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).
125125

126126
```java
127127
public class Main extends AppCompatActivity implements Task.Callback {
@@ -140,8 +140,8 @@ public class Main extends AppCompatActivity implements Task.Callback {
140140
####**How are tasks retained?**
141141
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:
142142

143-
- `TaskActivity.getTaskManager()`;
144-
- `TaskFragment.getTaskManager()`;
143+
- `TaskActivityCompat.getTaskManager()`;
144+
- `TaskFragmentCompat.getTaskManager()`;
145145
- `TaskManager.getActivityTaskManager()` (super-advanced usage);
146146
- `TaskManager.getFragmentTaskManager()` (super-advanced usage);
147147

demo/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
android:theme="@style/AppTheme">
1717
</activity>
1818

19+
<activity
20+
android:name=".ActivityV11"
21+
android:label="@string/app_name"
22+
android:theme="@style/AppTheme">
23+
</activity>
24+
1925
<activity
2026
android:name=".Main"
2127
android:label="@string/app_name"
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.neotech.app.retainabletasksdemo;
2+
3+
import android.os.Bundle;
4+
import android.support.annotation.NonNull;
5+
import android.view.Gravity;
6+
import android.view.View;
7+
import android.view.ViewGroup;
8+
import android.widget.Button;
9+
import android.widget.FrameLayout;
10+
11+
import org.neotech.app.retainabletasksdemo.tasks.CountDownTask;
12+
import org.neotech.library.retainabletasks.Task;
13+
import org.neotech.library.retainabletasks.providers.TaskActivity;
14+
15+
/**
16+
* Created by Rolf on 4-3-2016.
17+
*/
18+
public class ActivityV11 extends TaskActivity implements View.OnClickListener, Task.AdvancedCallback {
19+
20+
private static final String TASK_COUNT_DOWN = "count-down";
21+
private Button button;
22+
23+
@Override
24+
protected void onCreate(Bundle savedInstanceState) {
25+
super.onCreate(savedInstanceState);
26+
27+
FrameLayout root = new FrameLayout(this);
28+
button = new Button(this);
29+
button.setText(R.string.task_retain_ui_state);
30+
button.setOnClickListener(this);
31+
32+
root.addView(button, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
33+
setContentView(root);
34+
}
35+
36+
@Override
37+
public Task.Callback onPreAttach(@NonNull Task<?, ?> task) {
38+
button.setEnabled(false);
39+
button.setText("" + task.getLastKnownProgress());
40+
return this;
41+
}
42+
43+
@Override
44+
public void onClick(View v) {
45+
CountDownTask task = new CountDownTask(TASK_COUNT_DOWN, 10);
46+
getTaskManager().execute(task, this);
47+
button.setEnabled(false);
48+
}
49+
50+
@Override
51+
public void onPreExecute(Task<?, ?> task) {
52+
53+
}
54+
55+
@Override
56+
public void onPostExecute(Task<?, ?> task) {
57+
button.setEnabled(true);
58+
button.setText(R.string.task_retain_ui_state);
59+
}
60+
61+
@Override
62+
public void onCanceled(Task<?, ?> task) {
63+
64+
}
65+
66+
@Override
67+
public void onProgressUpdate(Task<?, ?> task, Object progress) {
68+
button.setText("" + (int) progress);
69+
}
70+
}

demo/src/main/java/org/neotech/app/retainabletasksdemo/Main.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
import org.neotech.app.retainabletasksdemo.tasks.SimpleTask;
1616
import org.neotech.app.retainabletasksdemo.tasks.TaskWithoutCallback;
1717
import org.neotech.library.retainabletasks.Task;
18-
import org.neotech.library.retainabletasks.TaskActivity;
18+
import org.neotech.library.retainabletasks.providers.TaskActivityCompat;
1919
import org.neotech.library.retainabletasks.TaskExecutor;
2020

21-
public class Main extends TaskActivity implements View.OnClickListener, Task.AdvancedCallback, OnAlertDialogClickListener {
21+
public class Main extends TaskActivityCompat implements View.OnClickListener, Task.AdvancedCallback, OnAlertDialogClickListener {
2222

2323
private static final String TASK_RETAIN_UI_STATE = "retain-ui-state";
2424
private static final String TASK_PROGRESS = "progress-dialog";
@@ -35,6 +35,8 @@ protected void onCreate(Bundle savedInstanceState) {
3535
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
3636

3737
findViewById(R.id.button_open_fragment_activity).setOnClickListener(this);
38+
findViewById(R.id.button_open_v11_activity).setOnClickListener(this);
39+
3840
findViewById(R.id.fab).setOnClickListener(this);
3941
findViewById(R.id.button_no_ui_task).setOnClickListener(this);
4042
findViewById(R.id.button_progress_task).setOnClickListener(this);
@@ -83,6 +85,8 @@ public void onClick(View v) {
8385
retainUserInterfaceButton.setEnabled(false);
8486
} else if(id == R.id.button_open_fragment_activity){
8587
startActivity(new Intent(this, ActivityWithFragments.class));
88+
} else if(id == R.id.button_open_v11_activity){
89+
startActivity(new Intent(this, ActivityV11.class));
8690
}
8791
}
8892

demo/src/main/java/org/neotech/app/retainabletasksdemo/TestFragment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
import org.neotech.app.retainabletasksdemo.tasks.CountDownTask;
1313
import org.neotech.library.retainabletasks.Task;
14-
import org.neotech.library.retainabletasks.TaskFragment;
14+
import org.neotech.library.retainabletasks.providers.TaskFragmentCompat;
1515

1616
/**
1717
* Created by Rolf on 3-3-2016.
1818
*/
19-
public class TestFragment extends TaskFragment implements View.OnClickListener, Task.AdvancedCallback {
19+
public class TestFragment extends TaskFragmentCompat implements View.OnClickListener, Task.AdvancedCallback {
2020

2121
private Button button;
2222

demo/src/main/res/layout/content_main.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@
2222
android:id="@+id/button_open_fragment_activity"
2323
android:layout_height="wrap_content"
2424
android:layout_width="wrap_content"
25-
android:text="@string/text_open_fragment_activty" />
25+
android:text="@string/text_open_fragment_activity" />
26+
27+
<Button
28+
android:id="@+id/button_open_v11_activity"
29+
android:layout_height="wrap_content"
30+
android:layout_width="wrap_content"
31+
android:text="@string/text_open_v11_activity" />
32+
2633

2734
<Button
2835
android:id="@+id/button_no_ui_task"

demo/src/main/res/values/strings.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
<string name="navigation_drawer_open">Open navigation drawer</string>
1818
<string name="navigation_drawer_close">Close navigation drawer</string>
1919

20-
<string name="text_open_fragment_activty">Open fragment test activity</string>
20+
<string name="text_open_fragment_activity">Start fragment test activity</string>
21+
<string name="text_open_v11_activity">Start non-support library Activity</string>
22+
2123

2224
<string name="text_fragment_task_manager_explanation">"This Activity has three Fragments, each Fragment extends the TaskFragment and has its own TaskManager instance.
2325

library/src/main/java/org/neotech/library/retainabletasks/Task.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,11 +531,11 @@ public final Result get() throws InterruptedException, ExecutionException {
531531
}
532532

533533
/**
534-
* Returns the currently set callback listener..
534+
* Returns the currently set callback listener.
535535
* @return The currently set callback listener.
536536
*/
537537
@MainThread
538-
Callback getCallback(){
538+
public Callback getCallback(){
539539
return callback;
540540
}
541541

library/src/main/java/org/neotech/library/retainabletasks/TaskManager.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,30 @@ public interface TaskAttachListener {
7878
@MainThread
7979
public abstract boolean isRunning(@NonNull String tag);
8080

81+
@MainThread
82+
public abstract void assertAllTasksDetached() throws IllegalStateException;
83+
8184
private static volatile BaseTaskManager globalInstance;
85+
protected static volatile boolean strictDebug = false;
86+
87+
/**
88+
* Enables or disables the strict debug mode. When this mode is enabled the TaskManager does
89+
* some extra checking and throws exceptions if it detects faulty behaviour. You're encouraged
90+
* to use this mode when testing your app. Strict mode is disabled by default.
91+
* @param strictDebug true if the strict mode should be enabled, false if it should be disabled.
92+
*/
93+
public static void setStrictDebugMode(boolean strictDebug){
94+
TaskManager.strictDebug = strictDebug;
95+
}
8296

97+
/**
98+
* Returns whether the strict mode is enabled. By default the strict mode is disabled.
99+
* @return true if strict mode is enabled, false if not.
100+
* @see TaskManager#setStrictDebugMode(boolean)
101+
*/
102+
public static boolean isStrictDebugModeEnabled(){
103+
return strictDebug;
104+
}
83105

84106
/**
85107
* Returns the {@link TaskManager} associated with the given Fragment.
@@ -120,7 +142,6 @@ private static String getTaskManagerTag(@Nullable String fragmentTag) {
120142
throw new IllegalArgumentException("In order to associate a TaskManger with a Fragment the Fragment needs to have a tag.");
121143
}
122144

123-
124145
/**
125146
* Returns the {@link TaskManager} associated with the Activity the given FragmentManger belongs to. You
126147
* should never try to supply a child/Fragment FragmentManger here.

library/src/main/java/org/neotech/library/retainabletasks/TaskManagerLifeCycleProxy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public final class TaskManagerLifeCycleProxy {
1818
private final TaskManagerProvider provider;
1919

2020
public TaskManagerLifeCycleProxy(@NonNull TaskManagerProvider provider){
21-
if(!(provider instanceof Activity || provider instanceof Fragment || provider instanceof android.app.Fragment)){
21+
if(!(provider instanceof Activity || provider instanceof Fragment || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && provider instanceof android.app.Fragment))){
2222
throw new IllegalArgumentException("The TaskManagerProvider needs to be an instance of android.app.Activity (including the derived support library activities), android.app.Fragment or android.support.v4.app.Fragment!");
2323

2424
/**
@@ -50,7 +50,7 @@ public TaskManager getTaskManager(){
5050
fragmentTaskManager = (BaseTaskManager) TaskManager.getFragmentTaskManager((Fragment) provider);
5151
} else if(provider instanceof Activity){
5252
fragmentTaskManager = (BaseTaskManager) TaskManager.getActivityTaskManager(((Activity) provider).getFragmentManager());
53-
} else if(provider instanceof android.app.Fragment){
53+
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && provider instanceof android.app.Fragment){
5454
fragmentTaskManager = (BaseTaskManager) TaskManager.getFragmentTaskManager((android.app.Fragment) provider);
5555
} /* else {
5656
//This should never happen as the constructor checks everything.

0 commit comments

Comments
 (0)