惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
Simon Willison's Weblog
Simon Willison's Weblog
H
Help Net Security
F
Fortinet All Blogs
H
Heimdal Security Blog
S
Schneier on Security
L
LangChain Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
NISL@THU
NISL@THU
P
Palo Alto Networks Blog
J
Java Code Geeks
博客园 - 【当耐特】
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Vulnerabilities – Threatpost
I
InfoQ
Recorded Future
Recorded Future
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
CERT Recently Published Vulnerability Notes
T
Tenable Blog
腾讯CDC
C
Check Point Blog
量子位
M
MIT News - Artificial intelligence
GbyAI
GbyAI
罗磊的独立博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog
小众软件
小众软件
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
V2EX - 技术
V2EX - 技术
T
Threatpost
Engineering at Meta
Engineering at Meta
Attack and Defense Labs
Attack and Defense Labs
T
Tailwind CSS Blog
S
Securelist
The Cloudflare Blog
博客园 - 叶小钗
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
爱范儿
爱范儿

LengYue's Blog

在 Android 中实现 iOS 液态玻璃效果(二:折射与渗透效果) | LengYue's Blog 在 Android 中实现 iOS 液态玻璃效果 | LengYue's Blog Dart 单线程模型的本质 | LengYue's Blog 使用 Rust 开发 Android 底层库,并简化 Java 与 Rust 相互操作 | LengYue's Blog 将 Rust 编译为可在 Android 上使用的二进制文件 | LengYue's Blog 使用 GoMobile 创建 Android、iOS 跨平台 WebSocket Library | LengYue's Blog Flutter error not found dart html | LengYue's Blog AndroidStudio新版本Logcat | LengYue's Blog Typecho to Hugo | LengYue's Blog GetX Router 设置返回值 | LengYue's Blog Flutter 基础 | Dart 语法 mixin | LengYue's Blog 不使用第三方软件实现Obsidian多平台实时同步 | LengYue's Blog Android 使用字节码 hook 修复第三发 bug | LengYue's Blog 在 Jetpack Compose 中使用输入框(TextField )遇到的一些问题 | LengYue's Blog RecyclerView使用优化的ListAdapter | LengYue's Blog ⾃定义布局流程 | LengYue's Blog ViewModel之自定义构造函数 | LengYue's Blog Android Jetpack Compose 超快速上手指南 | LengYue's Blog android 11 [api 30] 适配指南 | LengYue's Blog Android 声明式 UI 框架 Litho 初探 —— Sections API | LengYue's Blog Android 声明式 UI 框架 Litho 初探 —— Layout | LengYue's Blog Android声明式UI框架 Litho 初探 —— MountSpec的使用 | LengYue's Blog Android声明式UI框架 Litho 初探——基础使用 | LengYue's Blog Android声明式UI框架 Litho 初探 ——两种数据类型 | LengYue's Blog
Android-使用@AutoService实现spi | LengYue's Blog
LengYue · 2021-07-22 · via LengYue's Blog

什么是 SPI?

Java SPI 全称 Service Provider Interface,是 Java 提供的一套用来被第三方实现或者扩展的 API,它可以用来启用框架扩展和替换组件。实际上是“基于接口的编程 + 策略模式 + 配置文件”组合实现的动态加载机制. 具体解释就是:

  • 定义一个接口文件
  • 写出多个该接口文件的实现
  • 在 src/main/resources/ 下建立 /META-INF/services 目录,新增一个以接口命名的文件 , 内容是要接口的实现类全路径
  • 使用 ServiceLoader 类 来获取到这些实现的接口

示例

  • 定义一个接口文件 - Book
    package com.apkdv.spi_test;
    public interface Book {
        String name();
    }
  • 实现两个接口
    package com.apkdv.spi_test;
    public class Android implements Book {
        @Override
        public String name() {
            return "Android";
        }
    }
    package com.apkdv.spi_test;
    public class Ios implements Book {
        @Override
        public String name() {
            return "iOS";
        }
    }
  • resources 目录下建立 /META-INF/services 目录,并建立已 com.apkdv.spi_test.Book 为命名的文件,然后把 AndroidIos 全路径添加进去 image.png
  • 使用 ServiceLoader 类读取 Book 接口实现类
    ServiceLoader<Book> load = ServiceLoader.load(Book.class);
            for (Book book : load) {
                System.out.println(book.name());
            }
  • 结果 image.png

可以看到这个过程跟我们平常获取到接口实现类的方式不一样,平常情况下要获取到实现类可能需要个集合然后把实现类一个个添加进去,而用 spi 就不用这样操作。这样在我们平常组件化开发中非常便利,提供了解耦化的路径。 但是使用起来却很不方便,最麻烦的就是要到 /META-INF/services 目录建立文件,不能动态添加。所以我们用到了 Google 的 @AutoService,他可以帮我们在编译的时候动态去生成这些东西,这样开发中就不用做太多其他复杂操作。

@AutoService 引入 (Koltin)

apply plugin: 'kotlin-kapt'
kapt 'com.google.auto.service:auto-service:1.0'
api 'com.google.auto.service:auto-service:1.0'

@AutoService 举例

创建一个接口文件

interface Book {
    fun name() :String
}

创建两个继承

  • Android-Book
    @AutoService(Book::class)
    class Android :Book {
        override fun name():String {
            return "Android"
        }
    }
  • iOS-Book
    @AutoService(Book::class)
    class IOS :Book {
        override fun name(): String {
            return "ios"
        }
    }

获取继承类

private fun getBookList() {
        val bookList = ServiceLoader.load(Book::class.java, javaClass.classLoader).toList()
        bookList.forEach {
            Log.d("MainActivity", it.name())
        }
    }

结果

image.png 可以看到获取到了两个继承类,并且不是空!