在Android上使用SPI机制

一. SPI即Service Provider Interfaces.
有时候一个接口可能有多种实现方式, 如果将特定实现写死在代码里面, 那么要更换实现的时候就要改动代码, 对原有代码进行重写. 这样非常麻烦, 而且也容易导致bug. Java提供了一种方式, 让我们可以对接口的实现进行动态替换, 这就是SPI机制. SPI机制非常简单, 步骤如下:

  1. 定义接口
  2. 定义接口的实现
  3. 创建resources/META-INF/services目录
  4. 在上一步创建的目录下创建一个以接口名(类的全名) 命名的文件, 文件的内容是实现类的类名 (类的全名), 如:
  • 在services目录下创建的文件是com.stone.imageloader.ImageLoader 文件中的内容为ImageLoader接口的实现类, 可能是com.stone.imageloader.impl.FrescoImageLoader
  1. 使用ServiceLoader查找接口的实现.

spi机制将接口和实现分开, 方便实现的动态替换. 这就是面向接口编程, 其好处是显而易见的.

二. Android App应用也是用Java编写的, 因此SPI在Android中同样是可以使用的.
Android上使用SPI的步骤和Java中是一样的. 下面给出实例:

  • (1) 创建spi接口, 如下:
package com.stone.image.spi;

public interface ImageLoader {
    void displayImage();
}
  • (2) 实现spi接口, 如下:
package com.stone.image.spi.impl;

import android.util.Log;

import com.stone.image.spi.ImageLoader;

public class FrescoImageLoader implements ImageLoader {

    @Override
    public void displayImage() {
        Log.e("_fresco_", this.getClass().getName() + " - displayImage: Hello world !");
    }
    
}
  • (3) 创建目录resources/META-INF/services目录

  • (4) 创建以接口命名的文件(com.stone.image.spi.ImageLoader), 内容为接口的实现类. 下面是spi的描述文件:

    在Android上使用SPI机制_第1张图片
    定义接口的实现的描述文件.png

  • (5) 使用ServiceLoader动态查找接口的实现并使用.
    下面是在Activity中查找接口的实现, 并调用接口的方法, 代码如下:

public class SpiActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_spi);


        findViewById(R.id.spi_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //下面调用方式都ok
//                ServiceLoader serviceLoader = ServiceLoader.load(ImageLoader.class);
//                ServiceLoader serviceLoader = ServiceLoader.load(ImageLoader.class, this.getClass().getClassLoader());
                ServiceLoader serviceLoader = ServiceLoader.load(ImageLoader.class, ImageLoader.class.getClassLoader());
                Iterator it = serviceLoader.iterator();
                if (it.hasNext()) {
                    it.next().displayImage();
                }
            }
        });
    }

}

点击按钮会输出下面信息:

com.stone.image.spi.impl.FrescoImageLoader - displayImage: Hello world !

关于spi在Android中的使用场景, 大家可以自己发掘 。◕‿◕。 .......

你可能感兴趣的:(在Android上使用SPI机制)