The context is an immutable runtime object that holds the configured state and manages the lifecycle of a Pi4J instance. It includes all loaded plugins, providers, platforms, I/O instance registry, environmental configuration and runtime objects including executor thread pools, I/O event listeners, etc.
Terminating/destroying the context stops and releases all resources, threads, listeners, and provisioned I/O instances held by the context.
Version 1 was implemented using a static singleton, while version 2 uses a “Context” to avoid static singletons.
A Pi4J Context can be created automatically (accepting all default context configurations) or manually (builder) allowing users to customize the context configuration.
An auto context includes AUTO-DETECT BINDINGS enabled which will load all detected Pi4J extension libraries (Platforms and Providers) in the class path. Note: Starting with 2.5.0-SNAPSHOT the Mock providers are not loaded. If the Mock providers are required see Alternate Context Creation With Mock Providers.
var pi4j = Pi4J.newAutoContext();
If you need more flexibility are specific use-cases, the builder can be used to define all the parameters of the context, for example when you want to use your own providers, use mocked instances for testing…:
Context pi4j = Pi4J.newContextBuilder()
.add(new MockPlatform())
.add(MockAnalogInputProvider.newInstance(),
MockAnalogOutputProvider.newInstance(),
MockSpiProvider.newInstance(),
MockPwmProvider.newInstance(),
MockSerialProvider.newInstance(),
MockI2CProvider.newInstance(),
MockDigitalInputProvider.newInstance(),
MockDigitalOutputProvider.newInstance())
.add(new MyCustomADCProvider(/* implements AnalogInputProvider, id="my-adc-prov" */))
.add(new MyCustomSPIProvider(/* implements SpiProvider, id="my-spi-prov" */))
.build();
The following code example will create a Context containing all the Mock Providers and Platform.
Context pi4j = Pi4J.newContextBuilder().autoDetectMockPlugins().autoDetectPlatforms().build();
A single Context
instance must be created in your application and shared between the classes. A Context
object contains
all the runtime and management state of the I/O. If you would use multiple Context
objects and attempt to reuse certain
I/O hardware or I/O providers it’s possible that they could conflict or get out of sync.
The Context
maintains a reference to each I/O instance created, until pi4j.shutdown()
is called.
Somewhere you will need to create()
your I/O instance giving it a unique ID (String). If you try to call create()
a second time with the same ID, you will get an IOAlreadyExistsException
.
pi4j.digitalOutput().create(1, "my-gpio");
Elsewhere in your application, you can get access to existing I/O instances using the Context’s io()
or getIO()
methods.
if (pi4j.hasIO("my-gpio")) {
DigitalOutput myOutput = pi4j.io("my-gpio");
}
Additional methods to access the registered I/O instances can be obtained through the Registry
class.
pi4j.registry().*