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

Commit b1fb065

Browse files
committed
Fixes #3 and #4
Annotation processor now casts Task objects to the required types for the @TaskProgress and @TaskAttach annotations. @TaskProgress now also supports a single argument function.
1 parent 2f079b5 commit b1fb065

File tree

4 files changed

+71
-27
lines changed

4 files changed

+71
-27
lines changed

annotations-processor/src/main/java/org/neotech/library/retainabletasks/AnnotationsProcessor.java

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,7 @@ private JavaFile createJavaFile(TypeElement forTypeElement, TaskBindingContainer
157157
callbackImplementation.addMethod(createTaskCallbackMethod("onPreExecute", methods.getElementForPreExecute()));
158158
callbackImplementation.addMethod(createTaskCallbackMethod("onPostExecute", methods.getElementForPostExecute()));
159159
callbackImplementation.addMethod(createTaskCallbackMethod("onCanceled", methods.getElementForCancel()));
160-
161-
MethodSpec.Builder progressUpdateMethod = MethodSpec.methodBuilder("onProgressUpdate")
162-
.addAnnotation(Override.class)
163-
.addModifiers(Modifier.PUBLIC)
164-
.addParameter(CLASS_TASK, "task")
165-
.addParameter(TypeName.OBJECT, "object");
166-
167-
if(methods.getElementForProgress() != null) {
168-
progressUpdateMethod.addStatement("target.$L(task, object)", methods.getElementForProgress().getSimpleName());
169-
}
170-
callbackImplementation.addMethod(progressUpdateMethod.build());
171-
160+
callbackImplementation.addMethod(createTaskCallbackMethodForProgress(methods.getElementForProgress()));
172161

173162
if(methods.getElementForAttach() != null) {
174163
final boolean onlyCallOnReAttach = methods.getElementForAttach().getAnnotation(TaskAttach.class).onlyCallOnReAttach();
@@ -179,7 +168,21 @@ private JavaFile createJavaFile(TypeElement forTypeElement, TaskBindingContainer
179168
if(parameters.size() == 0) {
180169
getListenerForMethod.addStatement("target.$L()", methods.getElementForAttach().getSimpleName());
181170
} else {
182-
getListenerForMethod.addStatement("target.$L(task)", methods.getElementForAttach().getSimpleName());
171+
// One parameter, check it and call the method.
172+
final VariableElement parameter = parameters.get(0);
173+
final TypeMirror taskType = processingEnv.getTypeUtils().erasure(processingEnv.getElementUtils().getTypeElement(CLASS_TASK.reflectionName()).asType());
174+
175+
if (!processingEnv.getTypeUtils().isAssignable(parameter.asType(), taskType)) {
176+
// Parameter not an instance of Task
177+
error(parameter, "Type of parameter '%s' is not an instance of '%s'!", parameter.getSimpleName(), taskType);
178+
} else {
179+
// Check if the class to cast too is accessible.
180+
final Element requiredElement = processingEnv.getTypeUtils().asElement(parameter.asType());
181+
if (!requiredElement.getModifiers().contains(Modifier.PUBLIC) && !requiredElement.getModifiers().contains(Modifier.PROTECTED)) {
182+
error(parameter, "Type of parameter '%s' is not public or protected accessible! This prevents Android-Retainable-Tasks from casting '%s' to '%s'.\nTo fix this either the type of the parameter or make the class accessible by adding the public or protected modifier!", parameter.getSimpleName(), taskType, parameter.asType().toString());
183+
}
184+
getListenerForMethod.addStatement("target.$L(($T) task)", methods.getElementForAttach().getSimpleName(), parameter.asType());
185+
}
183186
}
184187
if(onlyCallOnReAttach){
185188
getListenerForMethod.endControlFlow();
@@ -210,6 +213,47 @@ private JavaFile createJavaFile(TypeElement forTypeElement, TaskBindingContainer
210213
.build();
211214
}
212215

216+
private MethodSpec createTaskCallbackMethodForProgress(@Nullable Element progressElement){
217+
MethodSpec.Builder progressUpdateMethod = MethodSpec.methodBuilder("onProgressUpdate")
218+
.addAnnotation(Override.class)
219+
.addModifiers(Modifier.PUBLIC)
220+
.addParameter(CLASS_TASK, "task")
221+
.addParameter(TypeName.OBJECT, "object");
222+
223+
if(progressElement != null) {
224+
final List<? extends VariableElement> parameters = ((ExecutableElement) progressElement).getParameters();
225+
if(parameters.size() == 0) {
226+
progressUpdateMethod.addStatement("target.$L()", progressElement.getSimpleName());
227+
} else if(parameters.size() >= 1 && parameters.size() <= 2){
228+
// One or two parameters, check it and call the method.
229+
final VariableElement parameterTask = parameters.get(0);
230+
final TypeMirror taskType = processingEnv.getTypeUtils().erasure(processingEnv.getElementUtils().getTypeElement(CLASS_TASK.reflectionName()).asType());
231+
232+
if (!processingEnv.getTypeUtils().isAssignable(parameterTask.asType(), taskType)) {
233+
// Parameter not an instance of Task
234+
error(parameterTask, "Type of parameter '%s' is not an instance of '%s'!", parameterTask.getSimpleName(), taskType);
235+
return progressUpdateMethod.build();
236+
}
237+
// Check if the class to cast to is accessible.
238+
final Element requiredElement = processingEnv.getTypeUtils().asElement(parameterTask.asType());
239+
if (!requiredElement.getModifiers().contains(Modifier.PUBLIC) && !requiredElement.getModifiers().contains(Modifier.PROTECTED)) {
240+
error(parameterTask, "Type of parameter '%s' is not public or protected accessible! This prevents Android-Retainable-Tasks from casting '%s' to '%s'.\nTo fix this either the type of the parameter or make the class accessible by adding the public or protected modifier!", parameterTask.getSimpleName(), taskType, parameterTask.asType().toString());
241+
return progressUpdateMethod.build();
242+
}
243+
244+
if(parameters.size() == 2){
245+
progressUpdateMethod.addStatement("target.$L(($T) task, object)", progressElement.getSimpleName(), parameterTask.asType());
246+
} else {
247+
progressUpdateMethod.addStatement("target.$L(($T) task)", progressElement.getSimpleName(), parameterTask.asType());
248+
}
249+
250+
} else {
251+
progressUpdateMethod.addComment("No annotated method found for $L", progressElement.getSimpleName());
252+
}
253+
}
254+
return progressUpdateMethod.build();
255+
}
256+
213257
private MethodSpec createTaskCallbackMethod(String methodName, @Nullable Element methodToCall){
214258
// Create the implementation of the onPreExecute method.
215259
final MethodSpec.Builder onPreExecuteMethod = MethodSpec.methodBuilder(methodName)

demo/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdkVersion 25
4+
compileSdkVersion 26
55
buildToolsVersion '25.0.3'
66

77
defaultConfig {
88
applicationId "org.neotech.app.retainabletasksdemo"
99
minSdkVersion 14
10-
targetSdkVersion 25
10+
targetSdkVersion 26
1111
versionCode 1
1212
versionName "1.0"
1313
}
@@ -25,8 +25,8 @@ dependencies {
2525
annotationProcessor project(":annotations-processor")
2626
//compile 'org.neotech.library:android-retainable-tasks:1.0.0-rc-1'
2727

28-
compile 'com.android.support:appcompat-v7:25.3.1'
29-
compile 'com.android.support:design:25.3.1'
28+
compile 'com.android.support:appcompat-v7:26.0.2'
29+
compile 'com.android.support:design:26.0.2'
3030

3131
//LeakCanary is used to detect memory leaks in debug builds.
3232
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/ProgressTaskHandler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ public void execute(){
3434
}
3535

3636
@TaskAttach(TASK_PROGRESS)
37-
public void onAttach(Task task){
37+
public void onAttach(SimpleTask task){
3838
// Task attaches, make sure to show the progress dialog and update the progress if needed.
3939
progressDialog = ProgressDialog.showIfNotShowing(demoActivityAnnotations.getSupportFragmentManager(), DIALOG_PROGRESS);
4040
if(task.getLastKnownProgress() != null) {
41-
progressDialog.setProgress((Integer) task.getLastKnownProgress());
41+
progressDialog.setProgress(task.getLastKnownProgress());
4242
}
4343
}
4444

4545
@TaskProgress(TASK_PROGRESS)
46-
public void onProgress(Task<?, ?> task, Object progress){
47-
progressDialog.setProgress((int) progress);
46+
public void onProgress(SimpleTask task){
47+
progressDialog.setProgress(task.getLastKnownProgress());
4848
}
4949

5050
// Now this is cool, we can have a single method handle both the normal onPostExecute and the

library/build.gradle

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ group = GROUP
1111
version = VERSION_NAME
1212

1313
android {
14-
compileSdkVersion 25
14+
compileSdkVersion 26
1515
buildToolsVersion '25.0.3'
1616

1717
defaultConfig {
1818
minSdkVersion 14
19-
targetSdkVersion 25
19+
targetSdkVersion 26
2020
versionName = VERSION_NAME
2121
}
2222
buildTypes {
@@ -38,12 +38,12 @@ dependencies {
3838

3939
// Android Architecture Lifecycle library to support using the TaskManagerLifeCycleProxy in
4040
// combination with LifecycleOwner.getLifecycle().addObserver().
41-
compile 'android.arch.lifecycle:extensions:1.0.0-alpha3'
42-
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"
41+
compile 'android.arch.lifecycle:extensions:1.0.0-alpha9'
42+
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha9"
4343

4444
// Support library for the support library specific TaskManagerOwners (TaskActivityCompat).
45-
compile 'com.android.support:appcompat-v7:25.3.1'
46-
javadoc 'com.android.support:appcompat-v7:25.3.1'
45+
compile 'com.android.support:appcompat-v7:26.0.2'
46+
javadoc 'com.android.support:appcompat-v7:26.0.2'
4747

4848
testCompile 'junit:junit:4.12'
4949
}

0 commit comments

Comments
 (0)