AutoService路由

今天我們來看一款使用非常簡單的由google提供的Android 路由框架:AutoService(https://github.com/google/auto/tree/master/service)

話不多說,直接擼代碼

1.添加依賴

 dependencies{

 implementation'com.google.auto.service:auto-service:1.0-rc4'
 
 }

2.定義接口ITest

 public interface ITest {
 
 void test();

}

3.實現(xiàn)接口并添加注解

 import android.util.Log;
 
 import com.google.auto.service.AutoService;
 
 @AutoService(ITest.class)

 public class Testimplements ITest{
 
 @Override
 
     public void test() {
 
 Log.d("@@","sdd");
 
 }
 
 }

4.調(diào)用接口

 ServiceLoader.load(ITest.class).iterator().next().test();

5.看結(jié)果

輸出日志

接下來我們看看是怎么實現(xiàn)的:

進入java.util.ServiceLoader 類,ServiceLoader 實現(xiàn)了Iterable 接口,

 public final class ServiceLoader implements Iterable
ServiceLoader

看到這里,出現(xiàn)了兩個Iterable 對象,一個是providers,一個是lookupIterator ,他們又是哪來的呢?

load的時候返回了ServiceLoader對象

 public static ServiceLoader load(Class service) {

 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 
 return ServiceLoader.load(service, cl);
 
 }

這里驚喜的發(fā)現(xiàn)了lookupIterator 的來源,LazyIterator也實現(xiàn)了Iterable接口

 public void reload() {
 
 providers.clear();
 
 lookupIterator = new LazyIterator(service, loader);
 
 }

上面我們看到ServiceLoader 進行Iterable的時候,都會優(yōu)先調(diào)用providers.hasNext(), providers初始化的時候被clear了,就一定會進入lookupIterator.hasNext(),跟蹤代碼發(fā)現(xiàn),在加載文件名為 PREFIX +service.getName()的文件,并從文件parse出一個Iterable<String>對象,fullName 和 pending 先賣個關(guān)子

lookupIterator.hasNext()

接下來再看lookupIterator.next(),跟蹤發(fā)現(xiàn),在找Class并newCInstance一個對象,并存入providers中

lookupIterator.next()

看到這,揭曉fullName ,service就是我們調(diào)用ServiceLoader.load(ITest.class)傳入類,fullName 就是META-INF/services/接口的類名,

 private static final String PREFIX ="META-INF/services/";

總結(jié)一下:

fullName 就是META-INF/services/接口的類名,

providers就是一個存路由對象的Iterator,

pending 就是fullName文件中的實現(xiàn)類

我們打開APK包驗證下

APK包

好了,最后提兩個需要注意的點:

1.AutoService使用了APT技術(shù),需要在build.gradle文件中添加配置

 defaultConfig{
 
     javaCompileOptions{ annotationProcessorOptions{ includeCompileClasspath =true } }
 
 }

2.如果需要混淆,需要注意接口文件需要keep,例如

 -keep public class com.demo.** {*;}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容