1. Introduction
The SPI full name is the service Provider Interface, the provider interface, the service usually refers to an interface or an abstract class, the service provider is a concrete implementation of this interface or abstract class, by the third party to implement the interface to provide specific services. SPI provides a dynamic mechanism for extending applications, often as an extension of the framework service or as a replaceable service component, but is not widely used in Android.
The SPI application scenarios are mainly:
- Java Database Connectivity
- Java Cryptography Extension
- Java Naming and Directory Interface
- Java API for XML processing
- Java Business Integration
- Java Sound
- Java Image I/O
- Java File Systems
Official Introduction Document: Https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html
2. SPI mechanism
- Create a named file in the resources/meta-inf/services/directory that contains a
服务全限定名 服务的具体实现类的全限定名 specific implementation class that can write multiple services in the file
- Concrete implementation classes for dynamically loading services using the Serviceloader class
- The service-specific implementation class must have a constructor with no parameters
- If the specific implementation class of the service is in the jar package, it needs to be placed in the classpath of the main program
3. Use of SPI
SPI is rarely used in Android engineering, primarily because SPI is a mechanism that is set up for vendors or third-party service providers and is rarely used in regular projects. In today's increasingly complex business, many applications tend to be modular, and the project relies on many components, which can be problematic, how the main project communicates with the component, and how the components communicate. Of course there are many ways to solve the communication, here is an example of SPI.
Figure-1 Example
The main project relies on three components, respectively providing three service ABC, after the user switches backstage, the main program wants to turn off the positioning, but because the service ABC may be very sensitive to the location information changes, need to be a specific scenario for the service to tell the main program to turn off the location.
3.1 Defining interfaces or abstract classes
Defining interfaces
publicinterface IService { boolean keep();}
3.2 Implementing the interface
Defines three services to implement the interface, simplifying the logic to return directly.
Public class aservice implements iservice { @Override Public Boolean Keep() {return false; }} Public class bservice implements iservice { @Override Public Boolean Keep() {return false; }} Public class cservice implements iservice { @Override Public Boolean Keep() {return true; }}
3.3 Creating an SPI profile
In the main directory of the project to create a new directory resources/META-INF/services , the service interface name for the name of the new SPI profile, the content for the specific service implementation class permission naming, can have more than one.
Figure-2 directory structure diagram
The contents of the file are as follows:
com.spi.demo.AServicecom.spi.demo.BServicecom.spi.demo.CService
3.4 Invoking a specific service
Using Serviceloader to load the specific service class, and then traversing the specific implementation class, Serviceloader is actually going to read the contents of the META-INFO/services file in the directory, and then instantiate.
Mbtn.setonclicklistener (NewView.onclicklistener () {@Override Public void OnClick(View v) {serviceloader<iservice> loader = serviceloader.load (Iservice.class); iterator<iservice> Iterator = Loader.iterator ();BooleanIskeeploc =false; while(Iterator.hasnext ()) {if(Iterator.next (). Keep ()) {Iskeeploc =true; Break; }} toast.maketext (mainactivity. This,"Keep Location:"+ Iskeeploc, Toast.length_short). Show (); }});
4. Advantages of SPI
Only the service interface is provided, the specific service is implemented by other components, the interface and the concrete implementation are separated, and the collection of these implementation classes can be obtained through the serviceloader of the system, unified processing.
5. Disadvantages of SPI
- In Java, the SPI is published with the jar, each different jar can contain a series of SPI configuration, and on the Android platform, the application at the time of construction will eventually merge all the jar, so it is easy to cause the same SPI conflict, The common problem is the duplicatedzipentryexception exception
- Reading the SPI configuration information is read from the jar package at run time, because the APK is signed, and when read from the jar, the time-consuming issue of signature verification can cause performance loss
6. Optimization Ideas
Java in the use of Serviceloader to read the SPI configuration information is in the program run, we can put this read configuration information in advance, at compile time, through the Gradle plug-in, to scan the class file, find the specific service class (can be identified by labeling), The new Java file is then generated, which contains the specific implementation class.
This program at run time, you already know all the specific service class, the drawback is that the compilation time will be extended, you need to re-write a set of Read SPI information, generate Java files and other logic.
After optimization, the SPI has deviated from the original intention, but can do more things, can be separated from the business services, through the SPI to find business service portals, business components, a separate AAR, independent into the project.
7. Summary
SPI is a mechanism in Java, can be used directly in Android, but with some of the disadvantages mentioned above, we can refer to the SPI mechanism in Java, combined with the Android environment, output a new set of SPI mechanism.
Use of SPI in Android