Interface Callback and Observer Pattern
Callback is a very important feature in Java. For button click listener, it uses interface callback. I used to use interface callback often, but not very clearly understand it.
Interface and Callback
It is very easy to define an interface. Here we define a EatHelperInterface interface and it has a eat function.1
2
3interface EatHelperInterface {
void eat();
}
If this person is a Chinese, we just implement this interface.1
2
3
4
5
6public class Chinese implements EatHelperInterface{
public void eat() {
System.out.println("I need chopsticks to eat");
}
}
This is how we implement an interface. Also we can define many classes for different people. However, we don’t want so many class defined. It is better to define a People class to keep this interface, so that we can use callback to help different people to eat.1
2
3
4
5
6
7
8
9
10public class People {
interface EatHelperInterface eatHelperInterface;
public void setEatHelperInterface(EatHelperInterface eatHelperInterface){
this.eatHelperInterface = eatHelperInterface;
}
public void eatService(){
eatHelperInterface.eat();
}
}
setEatHelperInterface is to register the interface. People.eatService() is to execute the eat function of the interface. Our test can be like this.1
2
3
4
5
6
7public class Test {
public static void main(String[] args) {
People chinese = new people();
chinese.setEatHelperInterface(new Chinese());
chinese.eatService();
}
}
In many cases, we would like to use an anonymous inner class to define an interface.1
2
3
4
5
6
7
8
9
10
11
12public class Test {
public static void main(String[] args) {
People people = new people();
people.setEatHelperInterface(new EatHelperInterface() {
public void eat() {
System.out.println("I need **** to eat");
}
});
people.eatService();
}
}
Callback can separate the class which use this function and the one implement the function. Because the they do not care about each other. For any People, we just use people.eatService() to perform eat action. Different people pass different implementation into the interface.
Callback in Android
In Android development, for button click function, we have an interface OnClickListener and Button(View) contains this interface.
1 | public interface OnClickListener { |
1 | public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { |
This button that extends the view class is very similar with the People class, which contains the interface and execute its function.
For MainActivity we should ask for help how to perform this click function. We can implement the interface in MainActivity and pass this into OnClickListener, or we can use anonymous inner class.
1 | public class MainActivity extends Activity{ |
- Button -> People
- setOnClickListener -> setEatHeplerInterface
- onClickListener -> EatHelperInterface
- onClick -> eat
The difference of these two cases is that people.eatService() called in Test, but for button, only case to trigger the performClick is when we click the button (Not showing in code).
Observer Pattern
This is a simple Observer Pattern example. Observer A is very sensitive to some actions of observable B. A needs to do actions at the moment changes in B. Also look at the button example. When trigger button.performClick, OnClickListener need to react immediately.
Trigger: button Click -> view.performClick -> onClick
Hierarchy: (Button)View.setOnClickListener -> OnClickListener -> onClick
For Observer Patthern, there are FOUR component: Observer, subscribe, Observable, event. Observer subscribe Observable. when state of Observable changed, observer will know that(subscribe) and trigger its event based on this change.
- Button -> observable
- setOnClickListener -> subscribe
- onClickListener -> Observer
- onClick -> event
For observer pattern, it is an very useful pattern and we have many needs of it.
In Android development, we can easily to achieve infinite loading feature by observer pattern. For a recyclerview, every time it will show 10 items with data and one more item showing loading layout. In adapter onCreateViewHolder and onBindViewHolder we should implement this way.
1 |
|
So everytime when we scrolling to the last item which is VIEWTYPE_LOADING, it will trigger _onLoadMore function. It is like everytime we click button, performClick will triiger onClick function. When we setup adapter, we should implement this loadMoreListenner.onLoadmore function.
1 | shotListAdapter = new ShotListAdapter(new ArrayList<Shot>(), new ShotListAdapter.LoadMoreListener() { |
This LoadShotTask extends AsyncTask will use RESTful API to ask for next page of shots. This is a simple use of Interface Callback. The entire source code you can check from my Dribbble app.
Another place to use it is that when we want to refresh the content of a fragment, while the refresh button is not inside the fragment. We need to fresh the fragment from its parent activity. We should implement the listener by the observer pattern. Here is the simple example.
Another widely used of observer pattern is the RxJava.