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

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
A
About on SuperTechFans
量子位
G
Google Developers Blog
云风的 BLOG
云风的 BLOG
T
Threat Research - Cisco Blogs
Spread Privacy
Spread Privacy
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News and Events Feed by Topic
C
Cybersecurity and Infrastructure Security Agency CISA
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Tenable Blog
V
V2EX
月光博客
月光博客
L
Lohrmann on Cybersecurity
W
WeLiveSecurity
Webroot Blog
Webroot Blog
H
Hacker News: Front Page
酷 壳 – CoolShell
酷 壳 – CoolShell
T
The Exploit Database - CXSecurity.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 三生石上(FineUI控件)
T
Troy Hunt's Blog
Google Online Security Blog
Google Online Security Blog
AI
AI
腾讯CDC
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
Martin Fowler
Martin Fowler
博客园 - Franky
I
Intezer
Project Zero
Project Zero
I
InfoQ
P
Privacy International News Feed
C
Check Point Blog
T
The Blog of Author Tim Ferriss
P
Palo Alto Networks Blog
L
LINUX DO - 最新话题
有赞技术团队
有赞技术团队
Cloudbric
Cloudbric
人人都是产品经理
人人都是产品经理
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
SegmentFault 最新的问题
Latest news
Latest news
小众软件
小众软件

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 可以看到获取到了两个继承类,并且不是空!