some thoughts about callback

This blog will focus on how to use callback in a component.

What is callback?

Callback is a piece of executable code that can be passed around as an argument. It can be called to get executed whenever needed at a later time or immediately.

Why do we need callback in component?

When creating component, we pass to it many properties like height, width, etc. Besides this, we can also pass in a callback parameter so that we gives our component anther power to do some specific things.

When do we need callback?

Normally when the component UI layer detects some changes (e.g., user’s click), it needs to tell the controller in the back and trigger some completed data calculation or business logic. So how to trigger this? Call the callback.

The callback will be defined as a component property and will be passed in from the controller that creats this component. Then the component can further pass down this callback to it’s child component. When the inner most component receives an user event and decides it’s the time to execute the callback code in controller, it will simply needs to call the callback and the related code in controller will get execulated. Note that the callback is also a way for the inner most component to pass some data into the controller to do the calculation.

Where do we define callback interface?

Since callback is first defined in the root component as a property, we normally define this interface in the root component class.

Where do we create implementation for callback?

Since the controller that creates an instance of the root component will need to supply this callback, the implementation of a callback will need to be defined in the controller.

How do we pass around a callback method?

First, define in the root component.

Then, think about what data we want from the user event? Keep them as input arguments.

Next, think about is there data we want from the controller’s calculation so that we can use it directly in the child component? If yes, give the callback a return value, if not, leave the return value as void.

Then, we implement the callback in the controller where we want to create our root component.

Finally, pass this callback as a property when we create our root component.

Look at some examples

This will be a general pattern:

RootComponentSpec {
    Callback {
        doSomething();
    }
...    
}

Controller implements RootComponentSpec.Callback {
    @Override
    doSomething() {
        // the real calculation here.
    }

    RootComponent.create().callback(this);
}

// Somewhere inside the rootComponent has a childComponent. Rootcomponent passes this callback all the way down to the childComponent. 
ChildComponentSpec {
// Define a clickhandler.
    onclick() {
        mCallback.doSomething();
    }
}

Real Examples

When looking for callbacks, first think about what are the user events we want to handle?

  • Click media to select media
  • Click media to add to composer
  • Click permission block to ask for permission
  • Click camera to launch full screen camera
  • Click capture button to capture a photo
  • Click rotate button to rotate the screen
  • Click flash button to change the flash options

The first 3 are related to the left part of the camera row, so they can be inside callback interface 1. the last 4 are related to the right part of the camera row, so they will be inside callback interface 2.

Example 1:
About the media callback

Example 2:
About the camera callbakc

Some more thoughts

  • Callbacks associated with components are like clickHandlers. Components are UI elements and can’t not handle some click events. So these events needs to be handled by controller and callbacks are like a bridge to let component to directly talk to controller: Hey, I am clicked! Please do whatever you’re supposed to do!

  • Callbacks are like questionaires defined by UI component. UI put all the questions it doesn’t know where and ask controller for help. Controller answers all the questions in the questionaire, pass it to component when initiating the component.