您的位置:首页 > 移动开发 > Android开发

Android中的回调机制(基础理解)

2018-03-10 21:22 253 查看
      刚刚接触Android,但是已经听了很多次“回调函数”,“回调”等这样的字眼,于是自己感觉这个概念应该是android学习中非常重要的一个。直到前几天需要自己做一个有关下载更新的APK的时候,遇到问题了;我把本地数据,已安装APK数据以及网络请求数据进行解析比对之后,自动将所有APK的信息添加到一个自定义的ListView上,并添加相应的点击事件,最后展示给用户。但是在检测更新与查看APK描述信息需要修改UI的时候发现,我只能在listView中条目被点击了之后才知道本次要添加的数据;然后就用到了点击事件触发回调,根据被点击条目信息修改UI的目的。看似很简单,但是这种思想真的很厉害。

1,回调的概念
我也是在网上看了一些资料,大家各抒己见,自己还是比较混乱的。于是我就各种查阅,自己下了一个很绕口的定义:
      调用者中的部分功能实现是通过调用其他包含部分功能未实现的被调用者来实现的,而且自己根据具体需求,对被调用者未实现功能进行实现并提供给被调用者调用,从而达到了灵活实现自身的个性功能需求的目的。
真的很绕口,下面还是举一个例子吧。
      有一个类A,里面有一个方法a(),有一个类B,里面有一个方法b(),有一个接口C,里面有一个方法c();现在有这样一种情况,就是a()调用了b(),b()方法调用了c(),但是了,a()方法在调用的时候,根据情况的不同,需要c(),实现的目的是不一样的。也就是C的任意实现子类的c()方法都有可能被调用,关键是只有在执行到a()方法的时候才知道哪一个被调用。这里面就存在以下几个问题:
(1)我不可能列举完C的所有实现类,即便可以,后期扩展了也不好办;所以问题不能这样解决
(2)b()方法调用没有子类的C的c()方法是完成不了a()对b()的期望功能的,也更不可能B去实现C,这样就会出现和上面一样的问题
(3)b()方法的实现必须要C的一个实现类才能完成

怎么办了,于是回调就来了;仔细分析描述和定义:
(1)a()是调用者
(2)b()是被调用者
(3)c()是b()的部分未实现功能(因为目前还没有实现类)
那么还差下面两条就组成了一个完整的定义,并且加上下面这两个,问题也就很灵活的解决了:
(4)a()中实现c()就是调用者对被调用者部分未实现功能的实现,通常a()中需要传入一个C的匿名实现类
(5)a()调用b(),b()通过调用a()中对c()的实现,这就是回调

2,举例说明
      这里举例就拿我们最常见的按钮点击事件,这是系统自己实现的回调例子。
我们在写的时候,通常就一步:btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//具体实现
if (TestActivity.APKInstallStatus.get(apkName).equals("1")) {
String path = UpdateUtils.getSDCardDir() + "/" + apkName + ".apk";
TigerFileRequest request = new TigerFileRequest(TestActivity.newAPKLink.get(apkName), path);
TestActivity.downloadAndInstall(request, path, apkName);
} else {
TestActivity.downloadAndInstallInfo.setText("");
TestActivity.downloadAndInstallInfo.append(apkName + "当前已是最新版本\n");
}
}
       其中,btu是一个Button,因为是系统实现回调,所以我们只要对上面说的C的c()进行实现即可。下面来具体分析一下源码就会发现与我的定义是完全一致的。
(1)Button是A,setOnClickListner()是a();
(2)View.OnClickListener()是C,onClick()是c();
好像还少了一个B和b();没有关系,我们点开setOnClickListner()的源码,也就是a()的代码,其内容如下:public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}好了,这其中,getListenerInfo()返回的是一个ListenerInfo对象,而b()显然就是对ListenerInfo实例中的mOnclickListener赋值,所以:
(3)所以ListenerInfo就是B,getListenerInfo().mOnclickListener=1就是b()。
   这样,整个流程就完全通了。自定义的案列我觉得理解了这种思想根本就没有必要写了,因为写个例子很简单,关键是能不能理解这种用法的巧妙所在。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息