先给一个,我对回调机制的认识:回调就是我不知道你调用这个 具体 干吗,可是我知道你 大概 要干吗android
好比点击,写源码的人不知道点击按钮以后登录,仍是弹出对话框,可是写源码的人知道按钮加载出来而且人的手触摸并抬起这个动做就是点击。咱们先不看android的点击事件,咱们先本身作一个回调。程序员
想象一个场景(郑重承诺,本例不针对任何一我的,只是举例,若是引发不适,请关闭)bash
你们都上过学,学校的boss假设就是 校长 ,校长的工做是管理同窗们好好学习,快乐成长。可是一个校长管理不过来好几千名学生,因此要把工做分给 班主任 和 教导处主任 。网络
一个学校总有那么几个调皮捣蛋的学生,那么校长就得管管,管的方式假设有两种说(talk)和打(fuck),可是校长没时间,由于校长去开会了,就把任务交给班主任和教导处主任有可能还有别的老师。好了,校长在走以前先定义好了说和打的模块。app
package TestCallBack;
/**
* 校长类(关于类名个人英文水平就这样,爱看不看)
* @author Robin
*
*/
public class XiaoZhang {
//工做的引用
DoJob mDoJob;
//定义工做类型
public interface DoJob {
void talk(String teacherName);//说
void fuck(String teacherName, String tool);//打
}
//对外暴露调用位置
public void setmDoJobCallBack(String teacherName, String tool, DoJob doJob) {
if (doJob != null) {
doJob.talk(teacherName);//工做是-->说
doJob.fuck(teacherName, tool);//工做是-->打
}
}
}
复制代码
校长走后,同窗们随心所欲,班主任见状不妙,立刻开始工做。eclipse
package TestCallBack;
import TestCallBack.XiaoZhang.DoJob;
/**
* 班主任
*
* @author Robin
*
*/
public class ClassTeacher implements DoJob {
public void talk(String teacherName) {
// 班主任开始跟学生交谈
System.out.println("班主任 "+teacherName + " 开始口头教育学生");
}
public void fuck(String teacherName, String tool) {
// 班主任开始干学生
System.out.println("班主任 "+teacherName + " 开始用 " + tool + " 打学生");
}
}
复制代码
(声明,咱们不提倡打学生)ide
班主任:喂,校长吗?我要管学生了
校长:好
因而校长就new 了一个对象,并把班主任传进来,让班主任管学生函数
XiaoZhang xz = new XiaoZhang();// 建立一个校长
xz.setmDoJobCallBack("李二狗", "教鞭", new ClassTeacher());
复制代码
log打印以下:(用eclipse怎么了?谁不是从ec过来的。。。)
工具
教导主任管理学生同理:
学习
package TestCallBack;
import TestCallBack.XiaoZhang.DoJob;
/**
* 教导处主任
*
* @author Robin
*
*/
public class JaoDaoChuTeacher implements DoJob {
public void talk(String teacherName) {
// 教导处主任开始跟学生聊天
System.out.println("教导处主任 " + teacherName + " 开始口头教育学生");
}
public void fuck(String teacherName, String tool) {
// 教导处主任开始打学生
System.out
.println("教导处主任 " + teacherName + " 开始用 " + tool + " 打学生");
}
}
复制代码
建立对象,并执行
XiaoZhang xz = new XiaoZhang();// 建立一个校长
xz.setmDoJobCallBack("蒙哥·卡恩", "斧头", new JaoDaoChuTeacher());
复制代码
log打印以下:
这个地方注意,若是我想改写教导主任的talk,fuck方法,怎么写?
xz.setmDoJobCallBack("蒙哥·卡恩", "斧头", new JaoDaoChuTeacher(){
@Override
public void talk(String teacherName) {
// super.talk(teacherName);
System.out.println(teacherName);//只打印教导主任的名字
}
@Override
public void fuck(String teacherName, String tool) {
super.fuck(teacherName, tool);//又想执行被教导主任打的方法
System.out.println("被教导主任请去喝茶嗑瓜子");//打完以后又喝茶嗑瓜子
}
});
复制代码
注意super,调用父类的方法。
打印以下:
校长发现,效果并很差,学生仍是很皮,因而,校长又另请高明,既不是教导处主任,也不是班主任,是一个新的角色,他叫robin,擅长用皮鞭,怎么写?
首先确定是要有一个校长的赞成,因此须要建立一个校长对象
XiaoZhang xz = new XiaoZhang();// 建立一个校长
xz.setmDoJobCallBack("robin", "皮鞭", new DoJob() {//注意这个地方是DoJob
public void talk(String teacherName) {
// TODO Auto-generated method stub
System.out.println(teacherName + " 和我谈话了");
}
public void fuck(String teacherName, String tool) {
// TODO Auto-generated method stub
System.out.println("艾妈,我被 " + teacherName + " 用 " + tool
+ " 打了");
}
});
复制代码
log:
最后让咱们再来审视一下,开头我提出来的
回调就是我不知道你调用这个 具体 干吗,可是我知道你 大概 要干什么。
校长让座这个管理学生的工做,校长不知道具体是谁来作,怎么作,可是校长知道管学生有说和打两种方式。这个 说 和 打 就是所谓的 回调函数
你觉得结束了?看看右边滚动条吧,孩子。这是开始,前面都是铺垫。(Java程序员适当翻看下面内容。)
问题来了,回调有个J8用?
最先开始,你们都知道我请求网络数据,通常都有两个回调方法
onSuccess
onFailed
没错,我就是用xUtils长大的。
上网查阅资料以后,这里用到的网络回调伪代码大概以下:
public static void sendHttpRequest(final String address,
final HttpCallbackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
...//这里用HttpUrlConnection取到数据
while ((line = reader.readLine()) != null) {//流转换,获得字符串
response.append(line);
}
if (listener != null) {
// 回调onSuccess()方法,携带数据
listener.onSuccess(response.toString());
}
} catch (Exception e) {
if (listener != null) {
// 回调onFailed()方法,携带报错信息
listener.onFailed(e);
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
复制代码
我以前也是似懂非懂,如今感受明白了很多。
你觉得完了?
android用到了不少回调机制,好比按钮的点击事件、线程的run()方法
下面开始讲Android里面的回调机制。
这篇文章不错,我引用一下,做者不要打我
juejin.im/entry/58c23…
里面说到这两个例子
1. 给RecyclerView的item添加点击事件
public class ClickAdapter extends RecyclerView.Adapter{
//定义接口实例
private OnClickItemListener mOnClickItemListener;
//设置接口实例的setter方法
public void setOnClickItemListener(OnClickItemListener onClickItemListener) {
mOnClickItemListener = onClickItemListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { . . . }
@Override
public void onBindViewHolder(ViewHolder holder, int position) { . . . }
@Override
public int getItemCount() { . . . }
public class ViewHolder extends RecyclerView.ViewHolder{
// ...
// 视图控件初始化
public ViewHolder(View itemView) { . . . }
/*绑定视图方法,在Adapter的onBindViewHolder中调用*/
public void bindHolder(final String text) {
mTextView.setText(text);
if (null != mOnClickItemListener) {
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//在点击事件中进行回调
mOnClickItemListener.onClick(text);
}
});
}
}
}
//建立内部接口
interface OnClickItemListener{
void onClick(String text);
}
}
复制代码
因此,接口回调能够总结为如下4步:
2.用子线程加载网络图片,并显示在主线程中
public class ImageUtil {
public static void loadeIamge(final String url, final LoadeImageListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
InputStream is = null;
BufferedInputStream bis = null;
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setConnectTimeout(5000);
connection.connect();
is = connection.getInputStream();
bis = new BufferedInputStream(is);
//拿到bitmap,通知(调用)onLoadeImageListener。
listener.onLoadeImageListener(BitmapFactory.decodeStream(bis));
} catch (Exception e) {
e.printStackTrace();
}finally {
CloseUtil.closeQuietly(is);
CloseUtil.closeQuietly(bis);
}
}
}).start();
}
public interface LoadeImageListener {
void onLoadeImageListener(Bitmap bitmap);
}
}
复制代码
上面的代码就是一个加载网络图片的工具类,能够发如今这里,没有定义接口实例,也没有定义接口实例的setter方法,而是直接用调用者那里传来的接口实例进行操做。
下面来看看调用者的实现:
final ImageView imageView = (ImageView) findViewById(R.id.image_view);
ImageUtil.loadeIamge(IMG_URL, new ImageUtil.LoadeImageListener() {
@Override
public void onLoadeImageListener(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
});
复制代码
完。喜欢的点个赞,你的支持是我最大的动力。