1 interface callback
1.1 interface callback concept
What is an interface callback
Interface callback means that the reference of the object created by the class using an interface can be assigned to the interface variable declared by the interface, and the interface variable can call the method of the interface implemented by the class. In fact, when the interface variable calls the method in the interface implemented by the class, it notifies the corresponding object to call the method of the interface. This process is called the interface callback of the object function.
interface People{ void peopleList(); } class Student implements People{ public void peopleList(){ System.out.println("I'm a student."); } } class Teacher implements People{ public void peopleList(){ System.out.println("I'm a teacher."); } } public class Example{ public static void main(String args[]){ People a; //Declare interface variables a=new Student(); //Instantiation, which stores the reference of the object in the interface variable a.peopleList(); //Interface callback a=new Teacher(); //Instantiation, which stores the reference of the object in the interface variable a.peopleList(); //Interface callback } } result: I'm a student. I'm a teacher.
Let's look at the concept of upcasting.
1.2 upward transformation
Shape s=new Circle();, Here, a circle object is created and the resulting reference is immediately assigned to shape. Through inheritance, circle is a shape.
Suppose you call a base class method (it has been overridden in the exported class):
s.draw();
Due to late binding (polymorphism), the Circle.draw() method will be called correctly.
1.3 difference between upward transformation and interface callback
It seems that upward transformation and interface callback are the same thing. Look at the following two sentences, both from Thinking in Java
The core reason for using interfaces: to be able to transform up to multiple base types. That is, multiple implementations of interfaces can be used to transform upward into multiple interface base types (see Chapter 6 of abstraction and interface for details).
Getting a reference to an interface from an object that implements an interface is essentially the same as transforming it into the base class of the object. (this sentence is extracted from the chapter Thinking in Java 3rd interface and internal classes)
Therefore, these two concepts explain a behavior from two aspects. The concept of interface callback emphasizes the function of using interface to realize the use right of callback object method. The upward transformation involves polymorphism and runtime binding.
1.4 realize the equivalent function of callback function with Java interface
Developers familiar with MS-Windows and X Window System event driven programming models are used to passing function pointers called (i.e. callbacks) when certain events occur. Java's object-oriented model does not support method pointers at present. Java's interface support provides a mechanism to obtain the equivalent function of callback. The trick is to define a simple interface and declare the method we want to call in the interface.
Suppose we want to be notified when an event occurs. We can define an interface:
InterestingEvent.java
package org.zj.sample; public interface InterestingEvent { public void interestingEvent (); }
This allows us to control any object of the class that implements the interface. Therefore, we don't have to care about any external type information.
The class that signals the event must wait for the object that implements the InterestingEvent interface and call the interestingEvent() method when appropriate.
EventNotifier.java
package org.zj.sample; public class EventNotifier { private InterestingEvent ie; private boolean somethingHappened; public EventNotifier(InterestingEvent event) { ie = event; // Save the event object for later use. somethingHappened = false; // There are no events to report. } public void doWork() { if (somethingHappened) { // Check the predicate set. ie.interestingEvent();// Signal the event by calling this method of the interface. } } public void setHappened(){//Set predicate. somethingHappened=true; } }
In the above example, the somethingHappened predicate is used to track whether an event should be triggered. Code that wants to receive event notifications must implement the InterestingEvent interface and pass its own reference to the event notifier.
CallMe.java
package org.zj.sample; public class CallMe implements InterestingEvent { @SuppressWarnings("unused") private EventNotifier en; public CallMe() { // Note that the EventNotifier (InterestingEvent event) should pass an interface type. // Next, pass this, the CallMe instance that implements the InterestingEvent interface, to //EventNotifier. That is, the so-called interface callback. en = new EventNotifier(this); // Create an event notifier and pass its own reference to it. } // Define the actual handler for the event. public void interestingEvent() { System.out.println("Call me Hello."); } }
Write a test class below.
Test.java
package org.zj.sample; public class Test { public static void main(String[] args) { EventNotifier en=new EventNotifier(new CallMe()); en.setHappened(); en.doWork(); } } result: Call me Hello.
1.5 in depth understanding through examples
Callback: that is, calling a method C in class B in class A, and then calling D in class A. in the B class, D is called callback method.
- Class A implementation interface callback - Background 1
- class A contains a reference b to class B -- background 2
class B has a method f(CallBack callback) with a callback parameter - background 3
Object a of a calls method f of B (callback callback) -- class a calls a method C of class B
Then B can call the A method in the f(CallBack callback) method B class calls a method D of class A.
/** * This is a callback interface * @author xiaanming * */ public interface CallBack { /** * @param result It's the answer */ public void solve(String result); } /** * @author xiaanming * A CallBack interface CallBack is implemented, which is equivalent to ----- > background one */ public class Wang implements CallBack { /** * Equivalent to ----- > background 2 */ private Li li; /** * @param li */ public Wang(Li li){ this.li = li; } /** * @param question */ public void askQuestion(final String question){ //One thread here is asynchronous, new Thread(new Runnable() { @Override public void run() { /** * This is equivalent to class A calling method C of B */ li.executeMessage(Wang.this, question); } }).start(); play(); } public void play(){ System.out.println("I'm going shopping"); } /** * */ @Override public void solve(String result) { System.out.println("Xiao Li told Xiao Wang the answer was--->" + result); } } /** * @author * */ public class Li { /** * It is equivalent to class B with f() --- > background 3 with the parameter CallBack callBack * @param callBack * @param question Questions asked by Xiao Wang */ public void executeMessage(CallBack callBack, String question){ System.out.println("Questions asked by Xiao Wang--->" + question); //It takes a long time to simulate things for(int i=0; i<10000;i++){ } /** * After Xiao Li finished his business, he thought the answer was 2 */ String result = "The answer is 2"; /** * So he called Xiao Wang and called the method in Xiao Wang * This is equivalent to class B calling method D of A in turn */ callBack.solve(result); } } /** * Test class * @author xiaanming * */ public class Test { public static void main(String[]args){ Li li = new Li(); Wang wang = new Wang(li); wang.askQuestion("1 + 1 = ?"); } }
Through the above example, do you almost understand the callback mechanism,
Look at the following example
//This is a callback interface of View /** * Interface definition for a callback to be invoked when a view is clicked. */ public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); }
package com.example.demoactivity; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * This is equivalent to Class A * @author xiaanming * The OnClickListener interface ----- > Background 1 is implemented */ public class MainActivity extends Activity implements OnClickListener{ /** * Class A Contains references to Class B ----- > background 2 */ private Button button; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button1); /** * Class A Call the method of View, and button extensions View ----- > class a calls a method C of class B */ button.setOnClickListener(this); } /** * The callback function called when the user clicks the Button. You can do what you want to do * What I do here is to prompt OnClick with Toast */ @Override public void onClick(View v) { Toast.makeText(getApplication(), "OnClick", Toast.LENGTH_LONG).show(); } }
The following is the setOnClickListener method of the View class, which is equivalent to class B. only the key code is posted
/** * This View is equivalent to class B * @author xiaanming * */ public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { /** * Listener used to dispatch click events. * This field should be made private, so it is hidden from the SDK. * {@hide} */ protected OnClickListener mOnClickListener; /** * setOnClickListener()The parameter of is OnClickListener interface ----- -- > background 3 * Register a callback to be invoked when this view is clicked. If this view is not * clickable, it becomes clickable. * * @param l The callback that will run * * @see #setClickable(boolean) */ public void setOnClickListener(OnClickListener l) { if (!isClickable()) { setClickable(true); } mOnClickListener = l; } /** * Call this view's OnClickListener, if it is defined. * * @return True there was an assigned OnClickListener that was called, false * otherwise is returned. */ public boolean performClick() { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); if (mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); //This is equivalent to class B calling a method D of class A. This D is the so-called callback method mOnClickListener.onClick(this); return true; } return false; } }