Skip to content

Commit cfddf8d

Browse files
committed
Merge pull request androidannotations#605 from rockytriton/604_check_currentThread_in_UiThread
added check for UI Thread
2 parents 3663dea + f48bdd9 commit cfddf8d

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

  • AndroidAnnotations

AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/UiThread.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,18 @@
3131
@Target(ElementType.METHOD)
3232
public @interface UiThread {
3333
long delay() default 0;
34+
35+
/**
36+
* If propagation = REUSE, the method will check first if it is inside the
37+
* UI thread already. If so, it will directly call the method instead of
38+
* using the handler. The default value is ENQUEUE, which will always call
39+
* the handler.
40+
*
41+
* @return
42+
*/
43+
Propagation propagation() default Propagation.ENQUEUE;
44+
45+
public enum Propagation {
46+
ENQUEUE, REUSE
47+
}
3448
}

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/UiThreadProcessor.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,29 @@
2222
import javax.lang.model.element.ExecutableElement;
2323

2424
import org.androidannotations.annotations.UiThread;
25+
import org.androidannotations.annotations.UiThread.Propagation;
2526
import org.androidannotations.helper.APTCodeModelHelper;
2627

28+
import android.os.Looper;
29+
30+
import com.sun.codemodel.JBlock;
2731
import com.sun.codemodel.JClass;
2832
import com.sun.codemodel.JClassAlreadyExistsException;
2933
import com.sun.codemodel.JCodeModel;
34+
import com.sun.codemodel.JConditional;
3035
import com.sun.codemodel.JDefinedClass;
3136
import com.sun.codemodel.JExpr;
37+
import com.sun.codemodel.JExpression;
3238
import com.sun.codemodel.JMethod;
3339
import com.sun.codemodel.JMod;
40+
import com.sun.codemodel.JOp;
3441

3542
public class UiThreadProcessor implements DecoratingElementProcessor {
3643

44+
private static final String METHOD_CUR_THREAD = "currentThread";
45+
private static final String METHOD_MAIN_LOOPER = "getMainLooper";
46+
private static final String METHOD_GET_THREAD = "getThread";
47+
3748
private final APTCodeModelHelper helper = new APTCodeModelHelper();
3849

3950
@Override
@@ -45,15 +56,15 @@ public String getTarget() {
4556
public void process(Element element, JCodeModel codeModel, EBeanHolder holder) throws JClassAlreadyExistsException {
4657

4758
ExecutableElement executableElement = (ExecutableElement) element;
59+
UiThread annotation = element.getAnnotation(UiThread.class);
60+
Propagation propagation = annotation.propagation();
4861

4962
JMethod delegatingMethod = helper.overrideAnnotatedMethod(executableElement, holder);
5063

5164
JDefinedClass anonymousRunnableClass = helper.createDelegatingAnonymousRunnableClass(holder, delegatingMethod);
5265

5366
{
5467
// Execute Runnable
55-
56-
UiThread annotation = element.getAnnotation(UiThread.class);
5768
long delay = annotation.delay();
5869

5970
if (holder.handler == null) {
@@ -62,6 +73,11 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) t
6273
}
6374

6475
if (delay == 0) {
76+
if (propagation == Propagation.REUSE) {
77+
// Put in the check for the UI thread.
78+
addUIThreadCheck(delegatingMethod, codeModel, holder);
79+
}
80+
6581
delegatingMethod.body().invoke(holder.handler, "post").arg(_new(anonymousRunnableClass));
6682
} else {
6783
delegatingMethod.body().invoke(holder.handler, "postDelayed").arg(_new(anonymousRunnableClass)).arg(lit(delay));
@@ -70,4 +86,29 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) t
7086

7187
}
7288

89+
/**
90+
* Add the pre-check to see if we are already in the UI thread.
91+
*
92+
* @param delegatingMethod
93+
* @param codeModel
94+
* @param holder
95+
* @throws JClassAlreadyExistsException
96+
*/
97+
private void addUIThreadCheck(JMethod delegatingMethod, JCodeModel codeModel, EBeanHolder holder) throws JClassAlreadyExistsException {
98+
// Get the Thread and Looper class.
99+
JClass tClass = codeModel.ref(Thread.class);
100+
JClass lClass = codeModel.ref(Looper.class);
101+
102+
// invoke the methods.
103+
JExpression lhs = tClass.staticInvoke(METHOD_CUR_THREAD);
104+
JExpression rhs = lClass.staticInvoke(METHOD_MAIN_LOOPER).invoke(METHOD_GET_THREAD);
105+
106+
// create the conditional and the block.
107+
JConditional con = delegatingMethod.body()._if(JOp.eq(lhs, rhs));
108+
JBlock thenBlock = con._then();
109+
110+
helper.callSuperMethod(delegatingMethod, holder, thenBlock);
111+
112+
thenBlock._return();
113+
}
73114
}

0 commit comments

Comments
 (0)