Android SPI

1.SPI

SPI全称Service Provider Interface,服务提供方接口,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。服务通常指一个接口或者一个抽象类,服务提供方是对这个接口或者抽象类的具体实现,由第三方来实现接口提供具体的服务。SPI其实就是为某个接口寻找服务的机制,它将装配的控制权移交给ServiceLoader,使用ServiceLoader去加载接口对应的实现,这样开发者就可以不用关注实现类。

开发中有时一个接口可能有多种实现方式,如果将特定实现写死在代码里面,那么要更换实现的时候就要改动代码,对原有代码进行重写,这样非常麻烦,而且也容易导致bug。使用SPI可以对接口的实现进行动态替换,即动态加载实现类。

SPI在模块开发中会比较有用,不同的模块可以基于接口编程,每个模块有不同的接口实现类,然后通过SPI机制自动注册到一个配置文件中,就可以实现在程序运行时扫描加载同一接口的不同实现类,从而实现跨模块通信。这样模块之间不会基于实现类硬编码,可插拔。

SPI整体机制如下:

Android SPI_第1张图片

Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。

 

2.SPI使用示例

SPI使用步骤:

①定义一个接口文件;

②写出多个该接口文件的实现;

③在src/main/resources/下新建/META-INF/services目录, 新增一个以接口命名的文件 , 文件内容是该接口的实现类全路径;

④使用ServiceLoader类查找这些接口的实现类。

通过例子看一下SPI在Android中的应用。先看工程结构图,有四个模块,一个是app主程序模块,一个是接口interface模块,另外两个就是接口的不同实现模块adisplay和bdisplay。

Android SPI_第2张图片

要实现的功能很简单,就是点击按钮,加载不同模块实现的方法,如下图所示:

Android SPI_第3张图片

①接口

首先是模块之间通信接口的实现,这里单独抽出一个模块interface,后面接口的不同实现模块可以都依赖同一个接口模块。

接口里面就是一个简单的方法:

package com.example;

public interface Display {

    String display();

}

②模块实现

接下来就是用不同的模块实现接口,首先需要在模块的build.gradle中加入接口的依赖:

dependencies {

    compile fileTree(include: ['*.jar'], dir: 'libs')

    compile project(':interface')

}

然后写一个简单的实现类实现接口Display。adisplay模块的实现类就是ADisplay.java:

package com.example;

public class ADispaly implements Display{

    @Override

    public String display() {

        return "This is display in module adisplay";

    }

}

bdisplay模块的实现类就是BDisplay.java:

package com.example;

public class BDisplay implements Display{

    @Override

    public Str

你可能感兴趣的:(android)