11package com .blankj .utilcode .util ;
22
33import android .support .annotation .NonNull ;
4+ import android .text .TextUtils ;
45import android .util .Log ;
56
7+ import java .io .IOException ;
68import java .lang .annotation .ElementType ;
79import java .lang .annotation .Retention ;
810import java .lang .annotation .RetentionPolicy ;
@@ -23,21 +25,23 @@ public final class ApiUtils {
2325
2426 private static final String TAG = "ApiUtils" ;
2527
28+ private static final String PREFIX = "blankj.api/" ;
29+
2630 private Map <Class , BaseApi > mApiMap = new ConcurrentHashMap <>();
2731 private Map <Class , Class > mInjectApiImplMap = new HashMap <>();
2832
2933 private ApiUtils () {
30- init ();
3134 }
3235
33- /**
34- * It'll be injected the implClasses who have {@link ApiUtils.Api} annotation
35- * by function of {@link ApiUtils#registerImpl} when execute transform task.
36- */
37- private void init () {/*inject*/ }
38-
3936 private void registerImpl (Class implClass ) {
40- mInjectApiImplMap .put (implClass .getSuperclass (), implClass );
37+ if (implClass == null ) return ;
38+ Class superclass = implClass .getSuperclass ();
39+ if (superclass == null ) return ;
40+ mInjectApiImplMap .put (superclass , implClass );
41+ }
42+
43+ public static void register (Class implClass ) {
44+ getInstance ().registerImpl (implClass );
4145 }
4246
4347 /**
@@ -57,7 +61,17 @@ public static String toString_() {
5761
5862 @ Override
5963 public String toString () {
60- return "ApiUtils: " + mInjectApiImplMap ;
64+ getAllApis ();
65+ StringBuilder sb = new StringBuilder ();
66+ sb .append ("ApiUtils {" );
67+ for (Map .Entry <Class , Class > entry : mInjectApiImplMap .entrySet ()) {
68+ sb .append ("\n " )
69+ .append (entry .getKey ().getName ())
70+ .append (": " )
71+ .append (entry .getValue ().getName ());
72+ }
73+ sb .append ("\n }" );
74+ return sb .toString ();
6175 }
6276
6377 private static ApiUtils getInstance () {
@@ -70,17 +84,17 @@ private <Result> Result getApiInner(Class apiClass) {
7084 synchronized (this ) {
7185 api = mApiMap .get (apiClass );
7286 if (api == null ) {
73- Class implClass = mInjectApiImplMap . get (apiClass );
87+ Class implClass = getApiImplClass (apiClass );
7488 if (implClass != null ) {
7589 try {
7690 api = (BaseApi ) implClass .newInstance ();
7791 mApiMap .put (apiClass , api );
7892 } catch (Exception ignore ) {
79- Log .e (TAG , "The <" + implClass + "> has no parameterless constructor." );
93+ Log .e (TAG , "The api of <" + implClass + "> has no parameterless constructor." );
8094 return null ;
8195 }
8296 } else {
83- Log .e (TAG , "The <" + apiClass + "> doesn't implement." );
97+ Log .e (TAG , "The api of <" + apiClass + "> doesn't implement." );
8498 return null ;
8599 }
86100 }
@@ -90,6 +104,73 @@ private <Result> Result getApiInner(Class apiClass) {
90104 return (Result ) api ;
91105 }
92106
107+ private Class getApiImplClass (Class apiClass ) {
108+ Class apiImplClass = mInjectApiImplMap .get (apiClass );
109+ if (apiImplClass != null ) return apiImplClass ;
110+ try {
111+ String [] apiImpls = Utils .getApp ().getAssets ().list (PREFIX + apiClass .getName ());
112+ if (apiImpls == null ) {
113+ return null ;
114+ }
115+ if (apiImpls .length != 1 ) {
116+ Log .e (TAG , "The api of <" + apiClass + "> has more than one implement." );
117+ return null ;
118+ }
119+ String apiImpl = apiImpls [0 ];
120+ if (TextUtils .isEmpty (apiImpl )) {
121+ Log .e (TAG , "The api of <" + apiClass + ">'s name is empty." );
122+ return null ;
123+ }
124+ String [] apiImpl_isMock = apiImpl .split ("-" );
125+ if (apiImpl_isMock .length != 2 ) {
126+ Log .e (TAG , "The api of <" + apiClass + ">'s implement <" + apiImpl
127+ + "> which format of name is wrong." );
128+ return null ;
129+ }
130+ String className = apiImpl_isMock [0 ];
131+ boolean isMock = Boolean .parseBoolean (apiImpl_isMock [1 ]);
132+ if (TextUtils .isEmpty (className )) {
133+ return null ;
134+ }
135+ apiImplClass = Class .forName (className );
136+ Class superclass = apiImplClass .getSuperclass ();
137+ if (superclass != null ) {
138+ //noinspection unchecked
139+ if (apiClass .isAssignableFrom (apiImplClass )) {
140+ mInjectApiImplMap .put (apiClass , apiImplClass );
141+ return apiImplClass ;
142+ } else {
143+ Log .e (TAG , "<" + apiImplClass .getName () + ">'s superClass is <"
144+ + superclass .getName () + ">, not <" + apiClass .getName () + ">" );
145+ return null ;
146+ }
147+ } else {
148+ Log .e (TAG , "<" + apiImplClass .getName () + ">'s superClass is <" +
149+ "null>, not <" + apiClass .getName () + ">" );
150+ return null ;
151+ }
152+ } catch (Exception e ) {
153+ e .printStackTrace ();
154+ return null ;
155+ }
156+ }
157+
158+ private void getAllApis () {
159+ try {
160+ String [] apis = Utils .getApp ().getAssets ().list (PREFIX );
161+ if (apis == null ) return ;
162+ for (String api : apis ) {
163+ try {
164+ getApiImplClass (Class .forName (api ));
165+ } catch (ClassNotFoundException e ) {
166+ e .printStackTrace ();
167+ }
168+ }
169+ } catch (IOException e ) {
170+ e .printStackTrace ();
171+ }
172+ }
173+
93174 private static class LazyHolder {
94175 private static final ApiUtils INSTANCE = new ApiUtils ();
95176 }
0 commit comments