1818import static com .sun .codemodel .JExpr .invoke ;
1919import static com .sun .codemodel .JExpr .ref ;
2020
21+ import java .util .List ;
22+
2123import javax .annotation .processing .ProcessingEnvironment ;
2224import javax .lang .model .element .Element ;
25+ import javax .lang .model .element .ExecutableElement ;
26+ import javax .lang .model .element .TypeElement ;
2327import javax .lang .model .type .TypeMirror ;
28+ import javax .lang .model .util .ElementFilter ;
2429
2530import org .androidannotations .annotations .res .DrawableRes ;
2631import org .androidannotations .annotations .res .HtmlRes ;
3641import org .androidannotations .rclass .IRClass ;
3742
3843import com .sun .codemodel .JBlock ;
44+ import com .sun .codemodel .JConditional ;
3945import com .sun .codemodel .JFieldRef ;
46+ import com .sun .codemodel .JVar ;
4047
4148public class ResHandler extends BaseAnnotationHandler <EComponentHolder > {
4249
50+ private static final int MIN_SDK_WITH_CONTEXT_GET_DRAWABLE = 21 ;
51+
4352 private AndroidRes androidRes ;
4453 private IdAnnotationHelper annotationHelper ;
4554
@@ -89,8 +98,9 @@ public void process(Element element, EComponentHolder holder) {
8998 // Special case for @HtmlRes
9099 if (element .getAnnotation (HtmlRes .class ) != null ) {
91100 methodBody .assign (ref (fieldName ), classes ().HTML .staticInvoke ("fromHtml" ).arg (invoke (holder .getResourcesRef (), resourceMethodName ).arg (idRef )));
92- } else if (element .getAnnotation (DrawableRes .class ) != null && hasContextCompatInClasspath ()) {
93- methodBody .assign (ref (fieldName ), classes ().CONTEXT_COMPAT .staticInvoke ("getDrawable" ).arg (holder .getContextRef ()).arg (idRef ));
101+ } else if (element .getAnnotation (DrawableRes .class ) != null ) {
102+ // Special case for @DrawableRes
103+ handleDrawableCompatibility (holder , ref (fieldName ), methodBody , idRef , resourceMethodName );
94104 } else {
95105 methodBody .assign (ref (fieldName ), invoke (holder .getResourcesRef (), resourceMethodName ).arg (idRef ));
96106 }
@@ -100,4 +110,51 @@ public void process(Element element, EComponentHolder holder) {
100110 protected boolean hasContextCompatInClasspath () {
101111 return processingEnvironment ().getElementUtils ().getTypeElement (CanonicalNameConstants .CONTEXT_COMPAT ) != null ;
102112 }
113+
114+ protected boolean shouldUseContextGetDrawableMethod () {
115+ return androidManifest .getMinSdkVersion () >= MIN_SDK_WITH_CONTEXT_GET_DRAWABLE ;
116+ }
117+
118+ protected boolean hasGetDrawableInContext () {
119+ TypeElement context = processingEnvironment ().getElementUtils ().getTypeElement (CanonicalNameConstants .CONTEXT );
120+
121+ return hasGetDrawable (context );
122+ }
123+
124+ private void handleDrawableCompatibility (EComponentHolder holder , JFieldRef ref , JBlock methodBody , JFieldRef idRef , String resourceMethodName ) {
125+ if (hasContextCompatInClasspath ()) {
126+ methodBody .assign (ref , classes ().CONTEXT_COMPAT .staticInvoke ("getDrawable" ).arg (holder .getContextRef ()).arg (idRef ));
127+ } else if (shouldUseContextGetDrawableMethod () && !hasContextCompatInClasspath ()) {
128+ methodBody .assign (ref , holder .getContextRef ().invoke ("getDrawable" ).arg (idRef ));
129+ } else if (!shouldUseContextGetDrawableMethod () && hasGetDrawableInContext () && !hasContextCompatInClasspath ()) {
130+ createCallWithIfGuard (holder , ref , methodBody , idRef );
131+ } else {
132+ methodBody .assign (ref , invoke (holder .getResourcesRef (), resourceMethodName ).arg (idRef ));
133+ }
134+ }
135+
136+ private void createCallWithIfGuard (EComponentHolder holder , JFieldRef ref , JBlock methodBody , JFieldRef idRef ) {
137+ JVar resourcesRef = holder .getResourcesRef ();
138+ JConditional guardIf = methodBody ._if (holder .classes ().BUILD_VERSION .staticRef ("SDK_INT" ).gte (holder .classes ().BUILD_VERSION_CODES .staticRef ("LOLLIPOP" )));
139+ JBlock ifBlock = guardIf ._then ();
140+ ifBlock .assign (ref , holder .getContextRef ().invoke ("getDrawable" ).arg (idRef ));
141+
142+ JBlock elseBlock = guardIf ._else ();
143+ elseBlock .assign (ref , resourcesRef .invoke ("getDrawable" ).arg (idRef ));
144+ }
145+
146+ private boolean hasGetDrawable (TypeElement type ) {
147+ if (type == null ) {
148+ return false ;
149+ }
150+
151+ List <? extends Element > allMembers = processingEnvironment ().getElementUtils ().getAllMembers (type );
152+ for (ExecutableElement element : ElementFilter .methodsIn (allMembers )) {
153+ if (element .getSimpleName ().contentEquals ("getDrawable" )) {
154+ return true ;
155+ }
156+ }
157+ return false ;
158+ }
159+
103160}
0 commit comments