1.什么是回调
回调的定义是在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A类去调用,这种机制就称为回调,这个定义比较正式,但看起来太绕了,一会A类一会B类,把人绕晕了。
使用日常生活中的例子来理解一下,回调英文单词是Callback,直译为回呼或者回电话,那就用跟电话有关作为例子吧,假设一个客户(客户是公司A的员工)问你(你是公司B的员工)一个问题,例如如何赚大钱,但这个问题你当场不能给出答案,以免显得很草率,这个时候你可以跟客户说,稍等一下,等确认后再给您回个电话,这样就可以挂了电话,想一下应该怎么回复客户,等有了答案后,再给客户回电话。这个过程使用到了回调机制。
再回头来理解回调函数的定义,客户就是A类,你是B类,而接口呢,指的是电话,接口的抽象方法,就是客户咨询你的问题的过程,确认问题这个过程当然得由你去实现,你实现之后(确定问题答案之后),再给客户回电话,完成回调过程。
2.为什么用回调
从打电话的例子可以看到回调的好处,分别是:
1.异步处理问题
如果不采用回调机制,客户需要一直在干等你的答案,你找答案的过程中,他啥也干不了,而采用回调方式后,客户不需要一直在电话前等回复,可以先忙自己的事去。在程序中,例如执行一个耗时的下载任务,最优的处理方式采用异步方式,即主程序启动下载后可以忙别的,下载程序执行完下载后告知主程序就行,这是异步处理带来的好处。
2.同一个事件有不同的处理方法
还是用客户打电话咨询问题的例子。当我们确认好问题要回客户的问题时,可以由你自己亲自回复,也可以由其他同事代回复,只要完成回复客户的约定即可。注意到回调定义中提到接口中的抽象方法,实现抽象方法方式多种多样,只要重写这个抽象方法就行。
3.代码例子
1.首先定义一个接口和抽象方法,如下:
//定义回调接口
public interface PhoneCallback{
void Counseling();
}
2.定义一个公司A的类,在该类中实现对接口的调用
public class CompanyA {
private PhoneCallback callBack;
public CompanyA(){
}
public String Work(PhoneCallback callBack){
//调用接口的抽象方法
String answer= callBack.Counseling();
return answer;
}
}
3.定义一个公司B的类,在该类中实现接口的抽象方法,也就是确定好答案回复客户的咨询
public class CompanyB implements PhoneCallback {
//重写抽象方法
@Override
public String Counseling() {
String answer="公司B的答复:这个问题建议您咨询有关部门";
return answer;
}
}
4.用界面展示以上的过程。其实以上已经完成了回调,这一步是用界面展示一下整个流程以及最终结果。
4.1 界面布局。布局很简单,一个Button按钮用于公司发起咨询和一个TextView展示结果。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/bCompany"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="27dp"
android:layout_marginTop="32dp"
android:text="公司A发起咨询"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
4.2 主界面MainActivity代码
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
Button bCommpanyA;
TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bCommpanyA=findViewById(R.id.bCompany);
tvResult=findViewById(R.id.tvResult);
bCommpanyA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CompanyA cA=new CompanyA();
CompanyB cB=new CompanyB();
String answer= cA.Work(cB);
tvResult.setText(answer);
}
});
}
}
4.3 结果展示,点击按钮后,TextView控件展示了公司B的回复
5.总结
理解回调的过程,关键需要捋清楚其中的关系,首先回调肯定涉及到多方(多个类)之间互动,例子中是公司A和公司B,其实还可以有公司C,D等加入,而他们之间沟通的媒介是接口(Interface)和抽象方法,接口相当于现实生活中电话,抽象方法相当于打电话咨询如何赚大钱,公司A可以咨询公司B如何赚大钱,也可以咨询公司C和公司D等如何赚大钱,而具体怎么回复,看各个公司想如何回复了,等他们想好了怎么回复,拿起电话打给公司A。关系捋清楚,已经算基本理解回调了。