Variables in Remixer

June 18, 2017 ยท View on GitHub

Table of Contents

Variables in Remixer

Variables are the cornerstone of Remixer, a change on a variable's value (by the Remixer UI, remote controller or any other means) triggers the callback (your code). Variables have a data type and (optionally) a constraint (which on Android are represented by subclasses of com.google.android.libraries.remixer).

Remixer has built-in support for 4 data types (Boolean, Color, Number and String), and you could add support for more types as explained in Extending Remixer.

Remixer guarantees that your callbacks are always called on the Main UI Thread for your application, but also makes no guarantee of thread-safety if you interact with remixer from other threads. Make sure you keep that in mind.

API Flavors

First of all you need to know that there are two ways to use variables, either directly through an explicit API in the form of Builders (all in package com.google.android.libraries.remixer) or through a convenient set of annotations found in com.google.android.libraries.remixer.annotations.

It is recommended you consistently use annotations unless you are extending Remixer.

In the explicit API you need to implement the com.google.android.libraries.remixer.Callback<T> interface to implement your callback and specify the DataType in the builder calls. In the annotation-based API you need to apply the annotation to a public method with one argument of the correct type and at the end of the activity's onCreate method you call RemixerBinder.bind(this).

There are a few very simple examples here of how to use both in the following sections, but you should look at the example activities and documentation for the explicit API and these annotations for more information.

Constraints

Unconstrained variables

Class: com.google.android.libraries.remixer.Variable

This is the base variable, it takes any possible value for the data type.

Properties

NameDescription
keyThe key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.
titleThe displayable name of the variable, if not set assumes key
contextAn activity where the variable is defined. Used to avoid memory leaks.
initialValueThe initial value.
callbackThe method to call once the variable value changes.
layoutIdA layoutId to display this, must implement RemixerWidget. It can remain unset and it will use a sensible default in each supported case.

Builder classes

ClassDescription
com.google.android.libraries.remixer.BaseVariableBuilderCan be used theoretically with any type.
com.google.android.libraries.remixer.BooleanVariableBuilderConvenience Variable builder that assumes false to be the initial value if unset.
com.google.android.libraries.remixer.StringVariableBuilderConvenience Variable builder that assumes the empty string to be the initial value if unset.

Annotations

  • com.google.android.libraries.remixer.annotation.BooleanVariableMethod
  • com.google.android.libraries.remixer.annotation.StringVariableMethod

Item-list variables

Class: com.google.android.libraries.remixer.ItemListVariable

These variables will throw an exception if the value is set to anything that isn't in its limitedToValues list.

Properties

This variable constraint has all of the properties of unconstrained variables in addition to:

NameDescription
limitedToValuesThe list of values this variable is limited to take.

Builder classes

ClassDescription
com.google.android.libraries.remixer.ItemListVariable.BuilderAssumes the first value in the limitedToValues list to be the initialValue if it is unset.

Annotations

  • com.google.android.libraries.remixer.annotation.ColorListVariableMethod
  • com.google.android.libraries.remixer.annotation.NumberListVariableMethod
  • com.google.android.libraries.remixer.annotation.StringListVariableMethod

Range variables

Class: com.google.android.libraries.remixer.RangeVariable

These variables are designed to work with Numbers only, and will throw an exception if the value is not within a specified range. Furthermore they have a concept of increments, so only values in the given increments are valid (for example, for a variable with {min: 0, increment: 5, max: 15}, 10 is a valid value, while 9 and 11 aren't)

Properties

This variable constraint has all of the properties of unconstrained variables in addition to:

NameDescription
minValueThe minimum value
maxValueThe maximum value
incrementThe increment between two steps of the range, 1 by default.

Builder classes

ClassDescription
com.google.android.libraries.remixer.RangeVariable.BuilderNo Description

Annotations

  • com.google.android.libraries.remixer.annotation.RangeVariableMethod

Data Types

Each data type has a type that represents it in runtime, a type that represents it while serialized (usually the same as the runtime one), and a converter between those types.

Furthermore, in order to display a Variable, there must be an appropriate widget for its combination of data type and constraints. Not all possible combinations are currently supported (or even make sense). This is further explained in the following sections.

Boolean

The boolean data type is pretty self explanatory. Because the boolean data type has only two possible values, true and false, no constraints are supported.

NameValue
Runtime typejava.lang.Boolean
Serializable typejava.lang.Boolean
Convertercom.google.android.libraries.remixer.serialization.converters.BooleanValueConverter
Supported constraintsUnconstrained variables (via com.google.android.libraries.remixer.ui.widget.BooleanVariableWidget)

Explicit API Boolean Variable

Variable<Boolean> variable = new BooleanVariableBuilder()
    .setKey("boolean")
    .setContext(this)
    .setCallback(new Callback<Boolean>() {
      @Override
      public void onValueSet(Boolean booleanValue) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based API Boolean Variable

A Boolean variable that has true as its initial value:

@BooleanVariableMethod(initialValue = true, key = "someRemixerKey")
public void setUseNewDialog(Boolean useNewDialog) {
}

Color

The Color data type lets you manipulate colors in the UI.

NameValue
Runtime typejava.lang.Integer It uses integer as its runtime type as that is the android-native way to represent colors.
Serializable typecom.google.android.libraries.remixer.serialization.SerializedColor it uses an intermediate type to serialize to be cross-platform friendly.
Convertercom.google.android.libraries.remixer.serialization.converters.ColorValueConverter
Supported constraintItem List Variables (via com.google.android.libraries.remixer.ui.widget.ColorListVariableWidget)

Theoretically we could support unconstrained variables, but we haven't built a good color picker. You're welcome to contribute one.

Explicit API Color List Variable

ItemListVariable<Integer> variable = new ItemListVariable.Builder<Integer>()
    .setLimitedToValues(new Integer[]{0xFF0000, 0x00FF00, 0x0000FF})
    .setKey("color")
    .setContext(this)
    .setDataType(DataType.COLOR)
    .setCallback(new Callback<Integer>() {
      @Override
      public void onValueSet(Integer color) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based Color List Variable

@ColorListVariableMethod(
    limitedToValues = {Color.parseColor("#000000"), Color.parseColor("#DCDCDC")})
public void setTitleColor(Integer color) {
}

Number

Remixer only supports Float numbers. These should work for most cases anyway.

NameValue
Runtime typejava.lang.Float
Serializable typejava.lang.Float
Convertercom.google.android.libraries.remixer.serialization.converters.NumberValueConverter
Supported constraintItem List Variables (via com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget)
Supported constraintRange Variables (via com.google.android.libraries.remixer.ui.widget.SeekBarRangeVariableWidget)

Theoretically we could support Unconstrained Variables if we write a usable control that handles non-number values correctly. You're welcome to contribute an implementation. |

Explicit API Number List Variable

ItemListVariable<Integer> variable = new ItemListVariable.Builder<Integer>()
    .setLimitedToValues(new Integer[]{1, 2, 3, 5, 8, 13, 21, 34})
    .setKey("number")
    .setContext(this)
    .setDataType(DataType.NUMBER)
    .setCallback(new Callback<Integer>() {
      @Override
      public void onValueSet(Integer number) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based Number List Variable

@NumberListVariableMethod(limitedToValues = {1, 2, 3, 5, 8, 13, 21, 34})
public void setFavoriteFibonacciNumber(Integer fibonacci) {
}

Explicit API Range Variable

ItemListVariable<Integer> variable = new ItemListVariable.Builder<Integer>()
    .setLimitedToValues(new Integer[]{1, 2, 3, 5, 8, 13, 21, 34})
    .setKey("number")
    .setContext(this)
    .setDataType(DataType.NUMBER)
    .setCallback(new Callback<Integer>() {
      @Override
      public void onValueSet(Integer number) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based Range Variable

A Range variable that goes from 15 to 70 and starts at 20 by default:

@RangeVariableMethod(minValue = 15, maxValue = 70, initialValue = 20)
public void setFontSize(Integer fontSize) {
}

String

The String data type lets you manipulate strings.

NameValue
Runtime typejava.lang.String
Serializable typejava.lang.String
Convertercom.google.android.libraries.remixer.serialization.converters.StringValueConverter
Supported constraintsItem List Variables (via com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget)
Supported constraintsUnconstrained Variables (via com.google.android.libraries.remixer.ui.widget.StringVariableWidget)

Explicit API String List Variable

ItemListVariable<String> variable = new ItemListVariable.Builder<Integer>()
    .setLimitedToValues(new String[]{"Roboto", "Roboto Mono", "Comic Sans MS"})
    .setKey("font")
    .setContext(this)
    .setDataType(DataType.STRING)
    .setCallback(new Callback<String>() {
      @Override
      public void onValueSet(String fontName) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based String List Variable

A String List variable that sets fonts from a list and defaults to the first in the list:

@StringListVariableMethod(limitedToValues = {"Roboto", "Roboto Mono", "Comic Sans MS"})
public void setTitleFont(String fontName) {
}

Explicit API String Variable

Variable<String> variable = new StringVariableBuilder()
    .setKey("string")
    .setContext(this)
    .setCallback(new Callback<String>() {
      @Override
      public void onValueSet(String string) {
        // ...
      }
    })
    .build()
Remixer.getInstance().addItem(variable);

Annotation-based String Variable

A String variable that sets freeform example text:

@StringVariableMethod
public void setExampleText(String exampleText) {
}