18
18
import android .os .StrictMode ;
19
19
import androidx .annotation .RestrictTo ;
20
20
import java .util .ArrayList ;
21
+ import java .util .HashSet ;
21
22
import java .util .List ;
22
23
import java .util .ServiceLoader ;
24
+ import java .util .Set ;
23
25
24
26
/**
25
27
* Wrapper class for {@link ServiceLoader} that disables StrictMode.
@@ -79,14 +81,16 @@ public static <T> T loadSingleService(Class<T> serviceClass, Factory<T> defaultI
79
81
80
82
/**
81
83
* A wrapper method around {@link #loadService(Class)} that returns one implementation of the
82
- * service or {@code null} if no implementation is found.
84
+ * service or {@code null} if no implementation is found. If an implementation is marked with
85
+ * {@link Supersedes}, the implementation in Supersedes will be filtered out.
83
86
*
84
87
* @param serviceClass the service type class to load implementation for
85
- * @return the implementing service or null if none is found.
88
+ * @return the implementing service or null if none is found. If an implementation is marked with
89
+ * {@link Supersedes}, the implementation in Supersedes will be filtered out.
86
90
* @throws IllegalStateException if more than one service implementations are found
87
91
*/
88
92
public static <T > T loadSingleServiceOrNull (Class <T > serviceClass ) {
89
- List <T > impls = ServiceLoaderWrapper .loadService (serviceClass );
93
+ List <T > impls = filter ( ServiceLoaderWrapper .loadService (serviceClass ) );
90
94
if (impls .isEmpty ()) {
91
95
return null ;
92
96
} else if (impls .size () == 1 ) {
@@ -102,4 +106,27 @@ public static <T> T loadSingleServiceOrNull(Class<T> serviceClass) {
102
106
"Found more than one implementation for " + serviceClass .getName () + combinedImpls );
103
107
}
104
108
}
109
+
110
+ @ SuppressWarnings ("unchecked" )
111
+ private static <T > List <T > filter (List <T > services ) {
112
+ Set <Class <?>> superseded = new HashSet <>();
113
+ for (T service : services ) {
114
+ Class <? extends T > clazz = (Class <? extends T >) service .getClass ();
115
+ Supersedes supersedes = clazz .getAnnotation (Supersedes .class );
116
+ if (supersedes != null ) {
117
+ superseded .add (supersedes .value ());
118
+ }
119
+ }
120
+ if (superseded .isEmpty ()) {
121
+ return services ;
122
+ } else {
123
+ List <T > filtered = new ArrayList <>();
124
+ for (T service : services ) {
125
+ if (!superseded .contains (service .getClass ())) {
126
+ filtered .add (service );
127
+ }
128
+ }
129
+ return filtered ;
130
+ }
131
+ }
105
132
}
0 commit comments