T
- The type of the build session variable. Must be loaded by a single class loader.public final class BuildSessionVariable<T>
extends java.lang.Object
JvmWideVariable
. However, it has one important extension: Its life time is limited to a build.
Specifically, a build session variable is initialized with a default value when the variable is first created and will be recreated and re-initialized (via the given default value supplier) at the start of every subsequent build within the same Gradle daemon.
This class addresses two potential issues when using static variables.
JvmWideVariable
; however, JvmWideVariable
does not handle the issue with the variables' life time, whereas BuildSessionVariable
can handle both issues.
This class requires that the buildStarted()
method be called every time the plugin is
applied and the buildFinished()
method be called at the end of a build. If the plugin is
applied multiple times, these methods may be called more than once in a build. This is currently
done in com.android.build.gradle.internal.BuildSessionHelper
.
A BuildSessionVariable
instance should typically be assigned to some static field of a
class, not to an instance field or a local variable within a method, since the actual build
session variable will not automatically be garbage-collected when it is no longer used, as one
would have expected from an instance field or a local variable. Additionally, this class
maintains a set of all BuildSessionVariable
instances that it creates (within the current
class loader), so creating instance fields or local variables of type BuildSessionVariable
would increase the size of this set with every new build, which is not what
we want.
The usage of this class is as follows. Suppose we previously used a static variable:
public final class Counter {
public static Integer COUNT = 0;
public static synchronized void increaseCounter() {
COUNT++;
}
}
We can then convert the static variable into a build session variable:
public final class Counter {
public static final BuildSessionVariable<Integer> COUNT =
new BuildSessionVariable<>("my.package.Counter", "COUNT", Integer.class, 0);
public static void increaseCounter() {
COUNT.executeRunnableSynchronously(() -> {
COUNT.set(COUNT.get() + 1);
});
}
}
Note that in the above example, Counter.COUNT
is still a static variable of Counter
, with the previously discussed limitations. What has changed is that Counter.COUNT
is now able to access a build session variable of type AtomicInteger
. (The
type of the build session variable after the conversion is the same as the type of the static
variable before the conversion.)
Where the context is clear, it might be easier to refer to variables of type BuildSessionVariable
as build session variables, although strictly speaking they are not, but
through them we can access build session variables.
This class is thread-safe.
JvmWideVariable
Constructor and Description |
---|
BuildSessionVariable(java.lang.String group,
java.lang.String name,
java.lang.Class<T> type,
T defaultValue)
Creates a
BuildSessionVariable instance that can access a build session variable. |
BuildSessionVariable(java.lang.String group,
java.lang.String name,
com.google.common.reflect.TypeToken<T> typeToken,
java.util.function.Supplier<T> defaultValueSupplier)
Creates a
BuildSessionVariable instance that can access a build session variable. |
Modifier and Type | Method and Description |
---|---|
static void |
buildFinished()
Releases the variable table and build session variables when a build is finished.
|
static void |
buildStarted()
Creates the variable table and initializes (or re-initializes) build session variables with
default values when a build starts.
|
<V> V |
executeCallableSynchronously(java.util.concurrent.Callable<V> action)
Executes the given action, where the execution is synchronized on the build session variable.
|
T |
get()
Returns the current value of this build session variable.
|
void |
set(T value)
Sets a value to this build session variable.
|
public BuildSessionVariable(@NonNull java.lang.String group, @NonNull java.lang.String name, @NonNull com.google.common.reflect.TypeToken<T> typeToken, @NonNull java.util.function.Supplier<T> defaultValueSupplier)
BuildSessionVariable
instance that can access a build session variable.
The group, name, type, and default value of the build session variable resemble the (fully qualified) name of the defining class of a static variable, the name of the static variable, its type, and its default value.
This method creates the build session variable and initializes it with the default value if the variable does not yet exist.
Unlike JVM-wide variables (see JvmWideVariable
), the build session variable will
be recreated and re-initialized (via the given value supplier) at the start of every
subsequent build within the same Gradle daemon.
A build session variable is uniquely defined by its group and name. The client should provide the same variable with the same type and default value. If the client provides a different type for a variable that already exists, it will result in a runtime casting exception. However, if the client provides a different default value for a variable that already exists, this method will simply ignore that value and will not throw an exception.
The type T
of the variable must be loaded by a single class loader. Currently,
this method requires the single class loader to be the bootstrap class loader.
The client needs to explicitly pass type T
via a Class
or a TypeToken
instance. This method takes a (TypeToken
as it is more general (it can
capture complex types such as Map<K, V>
). If the type is simple (can be represented
fully by a Class
instance), the client can use the BuildSessionVariable(String, String, Class, Object)
method instead.
group
- the group of the variablename
- the name of the variabletypeToken
- the type of the variabledefaultValueSupplier
- the supplier that produces the default value of the variable. It
is called only when the variable is first created. The supplied value can be null.JvmWideVariable.JvmWideVariable(String, String, TypeToken, Supplier)
public BuildSessionVariable(@NonNull java.lang.String group, @NonNull java.lang.String name, @NonNull java.lang.Class<T> type, @Nullable T defaultValue)
BuildSessionVariable
instance that can access a build session variable.
This method will call BuildSessionVariable(String, String, TypeToken, Supplier)
. See
the javadoc of that method for more details.public static void buildStarted()
public static void buildFinished()
@Nullable public T get()
public void set(@Nullable T value)
@Nullable public <V> V executeCallableSynchronously(@NonNull java.util.concurrent.Callable<V> action) throws java.util.concurrent.ExecutionException
This method is used to replace a static synchronized method operating on a static variable
when converting the static variable into a build session variable. (See the javadoc of BuildSessionVariable
.)
java.util.concurrent.ExecutionException
- if an exception occurred during the execution of the action